Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[engine] reland: always post tasks for platform channel responses. #55006

Merged
merged 6 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions shell/common/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Engine::Engine(
task_runners_(task_runners),
weak_factory_(this) {
pointer_data_dispatcher_ = dispatcher_maker(*this);
initial_route_ = settings_.route;
}

Engine::Engine(Delegate& delegate,
Expand Down
21 changes: 21 additions & 0 deletions shell/common/engine_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,27 @@ TEST_F(EngineTest, Create) {
});
}

TEST_F(EngineTest, CreateWithRoute) {
PostUITaskSync([this] {
auto settings = settings_;
settings.route = "/testo";
auto engine = std::make_unique<Engine>(
/*delegate=*/delegate_,
/*dispatcher_maker=*/dispatcher_maker_,
/*image_decoder_task_runner=*/image_decoder_task_runner_,
/*task_runners=*/task_runners_,
/*settings=*/settings,
/*animator=*/std::move(animator_),
/*io_manager=*/io_manager_,
/*font_collection=*/std::make_shared<FontCollection>(),
/*runtime_controller=*/std::move(runtime_controller_),
/*gpu_disabled_switch=*/std::make_shared<fml::SyncSwitch>());

EXPECT_TRUE(engine);
EXPECT_EQ(engine->InitialRoute(), "/testo");
});
}

TEST_F(EngineTest, DispatchPlatformMessageUnknown) {
PostUITaskSync([this] {
MockRuntimeDelegate client;
Expand Down
8 changes: 4 additions & 4 deletions shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1076,10 +1076,10 @@ void Shell::OnPlatformViewDispatchPlatformMessage(

// The static leak checker gets confused by the use of fml::MakeCopyable.
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetUITaskRunner(),
fml::MakeCopyable([engine = engine_->GetWeakPtr(),
message = std::move(message)]() mutable {
// This logic must always explicitly post a task so that we are guaranteed
// to wake up the UI message loop to flush tasks.
task_runners_.GetUITaskRunner()->PostTask(fml::MakeCopyable(
[engine = engine_->GetWeakPtr(), message = std::move(message)]() mutable {
if (engine) {
engine->DispatchPlatformMessage(std::move(message));
}
Expand Down
14 changes: 7 additions & 7 deletions shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -602,13 +602,6 @@ - (void)setUpChannels {
binaryMessenger:self.binaryMessenger
codec:[FlutterJSONMethodCodec sharedInstance]]);

if ([_initialRoute length] > 0) {
// Flutter isn't ready to receive this method call yet but the channel buffer will cache this.
[_navigationChannel invokeMethod:@"setInitialRoute" arguments:_initialRoute];
[_initialRoute release];
_initialRoute = nil;
}

_restorationChannel.reset([[FlutterMethodChannel alloc]
initWithName:@"flutter/restoration"
binaryMessenger:self.binaryMessenger
Expand Down Expand Up @@ -904,6 +897,13 @@ - (BOOL)createShell:(NSString*)entrypoint
_isGpuDisabled =
[UIApplication sharedApplication].applicationState == UIApplicationStateBackground;
#endif
// Override the setting route, as the dart project or function may have specified
// different values. During construction, the Engine constuctor will read the
// value of settings.route to determine the initial route value.
if (self.initialRoute) {
settings.route = [self.initialRoute UTF8String];
self.initialRoute = nil;
}

// Create the shell. This is a blocking operation.
std::unique_ptr<flutter::Shell> shell = flutter::Shell::Create(
Expand Down
14 changes: 7 additions & 7 deletions shell/platform/darwin/ios/framework/Source/FlutterEngineTest.mm
Original file line number Diff line number Diff line change
Expand Up @@ -201,17 +201,17 @@ - (void)testRunningInitialRouteSendsNavigationMessage {
// Run with an initial route.
[engine runWithEntrypoint:FlutterDefaultDartEntrypoint initialRoute:@"test"];

// Now check that an encoded method call has been made on the binary messenger to set the
// initial route to "test".
// Initial route is set directly in the shell/engine and should not send a platform
// channel message as it will arrive too late.
FlutterMethodCall* setInitialRouteMethodCall =
[FlutterMethodCall methodCallWithMethodName:@"setInitialRoute" arguments:@"test"];
NSData* encodedSetInitialRouteMethod =
[[FlutterJSONMethodCodec sharedInstance] encodeMethodCall:setInitialRouteMethodCall];
OCMVerify([mockBinaryMessenger sendOnChannel:@"flutter/navigation"
OCMReject([mockBinaryMessenger sendOnChannel:@"flutter/navigation"
message:encodedSetInitialRouteMethod]);
}

- (void)testInitialRouteSettingsSendsNavigationMessage {
- (void)testInitialRouteSettingsDoesNotSendNavigationMessage {
id mockBinaryMessenger = OCMClassMock([FlutterBinaryMessengerRelay class]);

auto settings = FLTDefaultSettingsForBundle();
Expand All @@ -221,13 +221,13 @@ - (void)testInitialRouteSettingsSendsNavigationMessage {
[engine setBinaryMessenger:mockBinaryMessenger];
[engine run];

// Now check that an encoded method call has been made on the binary messenger to set the
// initial route to "test".
// Initial route is set directly in the shell/engine and should not send a platform
// channel message as it will arrive too late.
FlutterMethodCall* setInitialRouteMethodCall =
[FlutterMethodCall methodCallWithMethodName:@"setInitialRoute" arguments:@"test"];
NSData* encodedSetInitialRouteMethod =
[[FlutterJSONMethodCodec sharedInstance] encodeMethodCall:setInitialRouteMethodCall];
OCMVerify([mockBinaryMessenger sendOnChannel:@"flutter/navigation"
OCMReject([mockBinaryMessenger sendOnChannel:@"flutter/navigation"
message:encodedSetInitialRouteMethod]);
}

Expand Down