提交 d1376fc9 编写于 作者: C Chinmay Garde

Allow PlatformMacMain to be called multiple times

It is called each time the embedder initializes a Flutter view controller. The Mac shell (which does not have a view controller), calls it before NSApplicationMain.

Common items like the base::AtExitManager and the platform message loop are stored in `EmbedderState`
上级 2e0ae759
......@@ -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") {
......
......@@ -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();
......
......@@ -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]));
}
......@@ -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);
}
......@@ -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);
......
......@@ -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<base::MessageLoopForUI> 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<EmbedderState> 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<EmbedderState>(argc, argv, icu_data_path);
});
return result;
}
static bool FlagsValidForCommandLineLaunch(const std::string& dart_main,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册