diff --git a/BUILD.gn b/BUILD.gn index 4fa947c2ed9fc8b3b806d5d109b041b9c206f3b6..31e251ce246047aa3faea4d0e4914022f3b0f64c 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -7,8 +7,14 @@ group("default") { testonly = true deps = [ "//sky", - "//sky/services/dynamic:sdk_lib", ] + + if (is_ios) { + deps += [ + "//sky/services/dynamic:sdk_lib", + "//sky/shell:flutter_framework", + ] + } } group("dist") { diff --git a/sky/shell/platform/ios/flutter_view_controller.mm b/sky/shell/platform/ios/flutter_view_controller.mm index 4dbb8b4f514c170696fb037e67b92d5846353a33..76ff4fecd503eca21b1d9151b50d980efada5c42 100644 --- a/sky/shell/platform/ios/flutter_view_controller.mm +++ b/sky/shell/platform/ios/flutter_view_controller.mm @@ -40,11 +40,6 @@ if (self) { _dartBundle = [dartBundleOrNil retain]; - NSBundle* bundle = [NSBundle bundleForClass:[self class]]; - NSString* icuDataPath = [bundle pathForResource:@"icudtl" ofType:@"dat"]; - - sky::shell::PlatformMacMain(0, nullptr, icuDataPath.UTF8String, nullptr); - [self performCommonViewControllerInitialization]; } @@ -75,6 +70,11 @@ _initialized = YES; + NSBundle* bundle = [NSBundle bundleForClass:[self class]]; + NSString* icuDataPath = [bundle pathForResource:@"icudtl" ofType:@"dat"]; + + sky::shell::PlatformMacMain(0, nullptr, icuDataPath.UTF8String); + _orientationPreferences = UIInterfaceOrientationMaskAll; _dynamicServiceLoader = [[FlutterDynamicServiceLoader alloc] init]; _viewportMetrics = sky::ViewportMetrics::New(); diff --git a/sky/shell/platform/ios/main_ios.mm b/sky/shell/platform/ios/main_ios.mm index 7b63743a23352855d1d776c830bb399e56dc3711..15ad04b9f53fa639e31393984bac5b91d0d7fdc9 100644 --- a/sky/shell/platform/ios/main_ios.mm +++ b/sky/shell/platform/ios/main_ios.mm @@ -8,8 +8,9 @@ #include "sky/shell/platform/mac/platform_mac.h" int main(int argc, const char* argv[]) { - return sky::shell::PlatformMacMain(argc, argv, "", ^() { - return UIApplicationMain(argc, (char**)argv, nil, - NSStringFromClass([FlutterAppDelegate class])); - }); + // iOS does use the FlutterViewController that initializes the platform but + // we have the command line args here. So call it now. + sky::shell::PlatformMacMain(argc, argv, ""); + return UIApplicationMain(argc, (char**)argv, nil, + NSStringFromClass([FlutterAppDelegate class])); } diff --git a/sky/shell/platform/mac/main_mac.mm b/sky/shell/platform/mac/main_mac.mm index ef2c4e1a9b00d26a413640a8400b8ae9fa385d5f..8f57340ccc022ac8a1a50b3ba7c507cfe90b2b96 100644 --- a/sky/shell/platform/mac/main_mac.mm +++ b/sky/shell/platform/mac/main_mac.mm @@ -32,21 +32,21 @@ void AttachMessageLoopToMainRunLoop(void) { int main(int argc, const char* argv[]) { [SkyApplication sharedApplication]; - return sky::shell::PlatformMacMain(argc, argv, "", ^() { - base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(sky::shell::switches::kHelp)) { - sky::shell::switches::PrintUsage("SkyShell"); - return EXIT_SUCCESS; - } - - if (command_line.HasSwitch(sky::shell::switches::kNonInteractive)) { - if (!sky::shell::InitForTesting()) - return 1; - base::MessageLoop::current()->Run(); - return EXIT_SUCCESS; - } - - sky::shell::AttachMessageLoopToMainRunLoop(); - return NSApplicationMain(argc, argv); - }); + sky::shell::PlatformMacMain(argc, argv, ""); + + base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(sky::shell::switches::kHelp)) { + sky::shell::switches::PrintUsage("SkyShell"); + return EXIT_SUCCESS; + } + + if (command_line.HasSwitch(sky::shell::switches::kNonInteractive)) { + if (!sky::shell::InitForTesting()) + return 1; + base::MessageLoop::current()->Run(); + return EXIT_SUCCESS; + } + + sky::shell::AttachMessageLoopToMainRunLoop(); + return NSApplicationMain(argc, argv); } diff --git a/sky/shell/platform/mac/platform_mac.h b/sky/shell/platform/mac/platform_mac.h index 309e2955069e75598edc6ccb01162709026a7097..48f5629b67ce8a9b78e5ed6d929e568b5b4db9bb 100644 --- a/sky/shell/platform/mac/platform_mac.h +++ b/sky/shell/platform/mac/platform_mac.h @@ -10,12 +10,7 @@ namespace sky { namespace shell { -typedef int (^PlatformMacMainCallback)(void); - -int PlatformMacMain(int argc, - const char* argv[], - std::string icu_data_path, - PlatformMacMainCallback callback); +void PlatformMacMain(int argc, const char* argv[], std::string icu_data_path); bool AttemptLaunchFromCommandLineSwitches(sky::SkyEnginePtr& engine); diff --git a/sky/shell/platform/mac/platform_mac.mm b/sky/shell/platform/mac/platform_mac.mm index de6c22844d4288dc14f027df34cf0fce877eca19..c1633ae6d14e06c6bacd9939fbead0785a43c21f 100644 --- a/sky/shell/platform/mac/platform_mac.mm +++ b/sky/shell/platform/mac/platform_mac.mm @@ -16,6 +16,7 @@ #include "base/message_loop/message_loop.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/simple_platform_support.h" +#include "sky/engine/wtf/MakeUnique.h" #include "sky/shell/shell.h" #include "sky/shell/switches.h" #include "sky/shell/tracing_controller.h" @@ -45,80 +46,60 @@ static void RedirectIOConnectionsToSyslog() { #endif } -int PlatformMacMainOnce(int argc, - const char* argv[], - std::string icu_data_path, - PlatformMacMainCallback callback) { - CHECK([NSThread currentThread] == [NSThread mainThread]) - << "Platform initialization must occur on the main platform thread"; +class EmbedderState { + public: + EmbedderState(int argc, const char* argv[], std::string icu_data_path) { + RedirectIOConnectionsToSyslog(); - base::mac::ScopedNSAutoreleasePool pool; + base::CommandLine::Init(argc, argv); - base::PlatformThread::SetName("platform_main"); + InitializeLogging(); - base::AtExitManager exit_manager; + base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(sky::shell::switches::kTraceStartup)) { + // Usually, all tracing within flutter is managed via the tracing + // controller + // The tracing controller is accessed via the shell instance. This means + // that tracing can only be enabled once that instance is created. Traces + // early in startup are lost. This enables tracing only in base manually + // till the tracing controller takes over. + sky::shell::TracingController::StartBaseTracing(); + } - RedirectIOConnectionsToSyslog(); + // This is about as early as tracing of any kind can start. Add an instant + // marker that can be used as a reference for startup. + TRACE_EVENT_INSTANT0("flutter", "main", TRACE_EVENT_SCOPE_PROCESS); - bool result = false; +#if TARGET_OS_IPHONE + // One cannot start the message loop on the platform main thread. Instead, + // we attach to the CFRunLoop + embedder_message_loop_.Attach(); +#endif - result = base::CommandLine::Init(argc, argv); - DLOG_ASSERT(result); + mojo::embedder::Init(mojo::embedder::CreateSimplePlatformSupport()); - InitializeLogging(); + CHECK(gfx::GLSurface::InitializeOneOff()); - base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(sky::shell::switches::kTraceStartup)) { - // Usually, all tracing within flutter is managed via the tracing controller - // The tracing controller is accessed via the shell instance. This means - // that tracing can only be enabled once that instance is created. Traces - // early in startup are lost. This enables tracing only in base manually - // till the tracing controller takes over. - sky::shell::TracingController::StartBaseTracing(); + sky::shell::Shell::InitStandalone(icu_data_path); } - // This is about as early as tracing of any kind can start. Add an instant - // marker that can be used as a reference for startup. - TRACE_EVENT_INSTANT0("flutter", "main", TRACE_EVENT_SCOPE_PROCESS); - - std::unique_ptr message_loop( - new base::MessageLoopForUI()); - -#if TARGET_OS_IPHONE - // One cannot start the message loop on the platform main thread. Instead, - // we attach to the CFRunLoop - message_loop->Attach(); -#endif - - mojo::embedder::Init(mojo::embedder::CreateSimplePlatformSupport()); - - CHECK(gfx::GLSurface::InitializeOneOff()); - sky::shell::Shell::InitStandalone(icu_data_path); + private: + base::AtExitManager exit_manager_; + base::MessageLoopForUI embedder_message_loop_; - int exit_code = callback != nullptr ? callback() : EXIT_SUCCESS; + DISALLOW_COPY_AND_ASSIGN(EmbedderState); +}; -#if !TARGET_OS_IPHONE - if (callback != nullptr) { - // If we control the embedder, the callback is what we use to wrap - // UIApplicationMain. If we are here, it means that that method has returned - // and we need to perform cleanup. - message_loop->QuitNow(); - } -#endif +void PlatformMacMain(int argc, const char* argv[], std::string icu_data_path) { + CHECK([NSThread isMainThread]) + << "Embedder initialization must occur on the main platform thread"; - return exit_code; -} + static std::unique_ptr g_embedder; + static std::once_flag once_main; -int PlatformMacMain(int argc, - const char* argv[], - std::string icu_data_path, - PlatformMacMainCallback callback) { - __block int result = EXIT_SUCCESS; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - result = PlatformMacMainOnce(argc, argv, icu_data_path, callback); + std::call_once(once_main, [&]() { + g_embedder = WTF::MakeUnique(argc, argv, icu_data_path); }); - return result; } static bool FlagsValidForCommandLineLaunch(const std::string& dart_main,