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

Allow specification of the FLX bundle (containing no Dart snapshot) outside...

Allow specification of the FLX bundle (containing no Dart snapshot) outside the iOS/Mac application bundle.

Allows launching of apps without having any Xcodebuild step in the simulator.
上级 d4f97e4f
......@@ -48,7 +48,7 @@ interface SkyEngine {
PushRoute(string route);
PopRoute();
RunFromFile(string main, string package_root);
RunFromFile(string main, string package_root, string bundle);
RunFromPrecompiledSnapshot(string path);
RunFromBundle(string path);
......
......@@ -3,13 +3,13 @@
// found in the LICENSE file.
#import <UIKit/UIKit.h>
#import "sky/shell/platform/ios/sky_app_delegate.h"
#include "sky/shell/platform/ios/sky_app_delegate.h"
#include "sky/shell/platform/mac/platform_mac.h"
int main(int argc, const char * argv[]) {
return PlatformMacMain(argc, argv, ^(){
return UIApplicationMain(argc, (char **)argv, nil,
int main(int argc, const char* argv[]) {
return sky::shell::PlatformMacMain(argc, argv, ^() {
return UIApplicationMain(argc, (char**)argv, nil,
NSStringFromClass([SkyAppDelegate class]));
});
}
......@@ -8,6 +8,7 @@
#import <OpenGLES/EAGL.h>
#import <OpenGLES/EAGLDrawable.h>
#include "base/command_line.h"
#include "base/logging.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
......@@ -15,10 +16,12 @@
#include "sky/services/engine/input_event.mojom.h"
#include "sky/services/pointer/pointer.mojom.h"
#include "sky/shell/platform/ios/sky_dynamic_service_loader.h"
#include "sky/shell/platform/mac/platform_mac.h"
#include "sky/shell/platform/mac/platform_service_provider.h"
#include "sky/shell/platform/mac/platform_view_mac.h"
#include "sky/shell/shell.h"
#include "sky/shell/shell_view.h"
#include "sky/shell/switches.h"
#include "sky/shell/ui_delegate.h"
#include <strings.h>
......@@ -226,7 +229,6 @@ static std::string TracesBasePath() {
// In case this runner is part of the precompilation SDK, the FLX bundle is
// present in the application bundle instead of the runner bundle. Attempt
// to resolve the path there first.
// TODO: Allow specification of the application bundle identifier
NSBundle* applicationBundle = [NSBundle
bundleWithIdentifier:@"io.flutter.application.FlutterApplication"];
NSString* path = [applicationBundle pathForResource:@"app" ofType:@"flx"];
......@@ -251,18 +253,44 @@ static std::string TracesBasePath() {
services->services_provided_by_embedder = service_provider.Pass();
_engine->SetServices(services.Pass());
mojo::String bundle_path([self flxBundlePath]);
CHECK(bundle_path.size() != 0)
<< "There must be a valid FLX bundle to run the application";
#if TARGET_IPHONE_SIMULATOR
[self runFromDartSource];
#else
[self runFromPrecompiledSource];
#endif
}
#if TARGET_IPHONE_SIMULATOR
_engine->RunFromBundle(bundle_path);
- (void)runFromDartSource {
if (sky::shell::AttemptLaunchFromCommandLineSwitches(_engine)) {
return;
}
UIAlertView* alert = [[UIAlertView alloc]
initWithTitle:@"Error"
message:@"Could not resolve one or all of either the main dart "
@"file path, the FLX bundle path or the package root "
@"on the host. Use the tooling to relaunch the "
@"application."
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
#else
- (void)runFromPrecompiledSource {
mojo::String bundle_path([self flxBundlePath]);
CHECK(bundle_path.size() != 0)
<< "There must be a valid FLX bundle to run the application";
_engine->RunFromPrecompiledSnapshot(bundle_path);
#endif
}
#endif // TARGET_IPHONE_SIMULATOR
#pragma mark - UIResponder overrides for raw touches
- (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase {
......
......@@ -32,7 +32,7 @@ void AttachMessageLoopToMainRunLoop(void) {
int main(int argc, const char* argv[]) {
[SkyApplication sharedApplication];
return PlatformMacMain(argc, argv, ^() {
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");
......
......@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SKY_SHELL_MAC_PLATFORM_MAC_H_
#define SKY_SHELL_MAC_PLATFORM_MAC_H_
#ifndef SKY_SHELL_PLATFORM_MAC_PLATFORM_MAC_H_
#define SKY_SHELL_PLATFORM_MAC_PLATFORM_MAC_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "sky/services/engine/sky_engine.mojom.h"
namespace sky {
namespace shell {
typedef int (^PlatformMacMainCallback)(void);
......@@ -15,8 +16,9 @@ int PlatformMacMain(int argc,
const char* argv[],
PlatformMacMainCallback callback);
#ifdef __cplusplus
}
#endif
bool AttemptLaunchFromCommandLineSwitches(sky::SkyEnginePtr& engine);
} // namespace shell
} // namespace sky
#endif // SKY_SHELL_MAC_PLATFORM_MAC_H_
#endif // SKY_SHELL_PLATFORM_MAC_PLATFORM_MAC_H_
......@@ -4,6 +4,8 @@
#include "sky/shell/platform/mac/platform_mac.h"
#include <Foundation/Foundation.h>
#include <asl.h>
#include "base/at_exit.h"
#include "base/command_line.h"
......@@ -21,6 +23,9 @@
#include "ui/gl/gl_surface.h"
#include "base/trace_event/trace_event.h"
namespace sky {
namespace shell {
static void InitializeLogging() {
logging::LoggingSettings settings;
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
......@@ -72,7 +77,8 @@ int PlatformMacMain(int argc,
// 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());
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,
......@@ -96,3 +102,95 @@ int PlatformMacMain(int argc,
return result;
}
static bool FlagsValidForCommandLineLaunch(const std::string& dart_main,
const std::string& package_root,
const std::string& bundle) {
if (dart_main.size() == 0 || package_root.size() == 0 || bundle.size() == 0) {
return false;
}
// Ensure that the paths exists. This catches cases where the user has
// successfully launched the application from the tooling but has since moved
// the source files on disk and is launching again directly.
NSFileManager* manager = [NSFileManager defaultManager];
if (![manager fileExistsAtPath:@(dart_main.c_str())]) {
return false;
}
if (![manager fileExistsAtPath:@(package_root.c_str())]) {
return false;
}
if (![manager fileExistsAtPath:@(bundle.c_str())]) {
return false;
}
return true;
}
static std::string ResolveCommandLineLaunchFlag(const char* name) {
auto command_line = *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(name)) {
return command_line.GetSwitchValueASCII(name);
}
const char* saved_default =
[[NSUserDefaults standardUserDefaults] stringForKey:@(name)].UTF8String;
if (saved_default != NULL) {
return saved_default;
}
return "";
}
bool AttemptLaunchFromCommandLineSwitches(sky::SkyEnginePtr& engine) {
base::mac::ScopedNSAutoreleasePool pool;
using namespace sky::shell::switches;
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
auto command_line = *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(kMainDartFile) ||
command_line.HasSwitch(kPackageRoot) || command_line.HasSwitch(kFLX)) {
// The main dart file, flx bundle and the package root must be specified in
// one go. We dont want to end up in a situation where we take one value
// from the command line and the others from user defaults. In case, any
// new flags are specified, forget about all the old ones.
[defaults removeObjectForKey:@(kMainDartFile)];
[defaults removeObjectForKey:@(kPackageRoot)];
[defaults removeObjectForKey:@(kFLX)];
[defaults synchronize];
}
std::string dart_main = ResolveCommandLineLaunchFlag(kMainDartFile);
std::string package_root = ResolveCommandLineLaunchFlag(kPackageRoot);
std::string bundle = ResolveCommandLineLaunchFlag(kFLX);
if (!FlagsValidForCommandLineLaunch(dart_main, package_root, bundle)) {
return false;
}
// Save the newly resolved dart main file and the package root to user
// defaults so that the next time the user launches the application in the
// simulator without the tooling, the application boots up.
[defaults setObject:@(dart_main.c_str()) forKey:@(kMainDartFile)];
[defaults setObject:@(package_root.c_str()) forKey:@(kPackageRoot)];
[defaults setObject:@(bundle.c_str()) forKey:@(kFLX)];
[defaults synchronize];
// Finally launch with the newly resolved arguments.
engine->RunFromFile(dart_main, package_root, bundle);
return true;
}
} // namespace shell
} // namespace sky
......@@ -8,6 +8,7 @@
#include "mojo/public/cpp/bindings/interface_request.h"
#include "sky/services/engine/input_event.mojom.h"
#include "sky/services/pointer/pointer.mojom.h"
#include "sky/shell/platform/mac/platform_mac.h"
#include "sky/shell/platform/mac/platform_view_mac.h"
#include "sky/shell/platform/mac/platform_service_provider.h"
#include "sky/shell/shell_view.h"
......@@ -16,8 +17,7 @@
#include "sky/shell/ui_delegate.h"
static void DynamicServiceResolve(const mojo::String& service_name,
mojo::ScopedMessagePipeHandle handle) {
}
mojo::ScopedMessagePipeHandle handle) {}
@interface SkyWindow ()<NSWindowDelegate>
......@@ -26,7 +26,8 @@ static void DynamicServiceResolve(const mojo::String& service_name,
@end
static inline pointer::PointerType EventTypeFromNSEventPhase(NSEventPhase phase) {
static inline pointer::PointerType EventTypeFromNSEventPhase(
NSEventPhase phase) {
switch (phase) {
case NSEventPhaseNone:
return pointer::PointerType::CANCEL;
......@@ -72,14 +73,8 @@ static inline pointer::PointerType EventTypeFromNSEventPhase(NSEventPhase phase)
self.platformView->SurfaceCreated(widget);
}
- (NSString*)skyInitialBundleURL {
return [[NSBundle mainBundle] pathForResource:@"app" ofType:@"flx"];
}
// TODO(eseidel): This does not belong in sky_window!
// Probably belongs in NSApplicationDelegate didFinishLaunching.
// We also want a separate setup for normal apps vs SkyShell
// normal apps only use a flx vs. SkyShell which always pulls from network.
- (void)setupAndLoadDart {
self.platformView->ConnectToEngine(mojo::GetProxy(&_sky_engine));
......@@ -90,9 +85,16 @@ static inline pointer::PointerType EventTypeFromNSEventPhase(NSEventPhase phase)
services->services_provided_by_embedder = service_provider.Pass();
_sky_engine->SetServices(services.Pass());
if (sky::shell::AttemptLaunchFromCommandLineSwitches(_sky_engine)) {
// This attempts launching from an FLX bundle that does not contain a
// dart snapshot.
return;
}
base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
std::string flx = command_line.GetSwitchValueASCII(sky::shell::switches::kFLX);
std::string flx =
command_line.GetSwitchValueASCII(sky::shell::switches::kFLX);
if (!flx.empty()) {
_sky_engine->RunFromBundle(flx);
return;
......@@ -100,15 +102,9 @@ static inline pointer::PointerType EventTypeFromNSEventPhase(NSEventPhase phase)
auto args = command_line.GetArgs();
if (args.size() > 0) {
_sky_engine->RunFromFile(args[0],
command_line.GetSwitchValueASCII(sky::shell::switches::kPackageRoot));
return;
}
NSString *endpoint = self.skyInitialBundleURL;
if (endpoint.length > 0) {
mojo::String string(endpoint.UTF8String);
_sky_engine->RunFromBundle(string);
auto package_root =
command_line.GetSwitchValueASCII(sky::shell::switches::kPackageRoot);
_sky_engine->RunFromFile(args[0], package_root, "");
return;
}
}
......
......@@ -14,6 +14,7 @@ const char kEnableCheckedMode[] = "enable-checked-mode";
const char kFLX[] = "flx";
const char kHelp[] = "help";
const char kNonInteractive[] = "non-interactive";
const char kMainDartFile[] = "dart-main";
const char kPackageRoot[] = "package-root";
const char kStartPaused[] = "start-paused";
const char kTraceStartup[] = "trace-startup";
......
......@@ -15,6 +15,7 @@ extern const char kEnableCheckedMode[];
extern const char kFLX[];
extern const char kHelp[];
extern const char kNonInteractive[];
extern const char kMainDartFile[];
extern const char kPackageRoot[];
extern const char kStartPaused[];
extern const char kTraceStartup[];
......
......@@ -22,8 +22,7 @@ static TestRunner* g_test_runner = nullptr;
} // namespace
TestRunner::TestRunner()
: shell_view_(new ShellView(Shell::Shared())),
weak_ptr_factory_(this) {
: shell_view_(new ShellView(Shell::Shared())), weak_ptr_factory_(this) {
CHECK(!g_test_runner) << "Only create one TestRunner.";
shell_view_->view()->ConnectToEngine(GetProxy(&sky_engine_));
......@@ -33,8 +32,7 @@ TestRunner::TestRunner()
sky_engine_->OnViewportMetricsChanged(metrics.Pass());
}
TestRunner::~TestRunner() {
}
TestRunner::~TestRunner() {}
TestRunner& TestRunner::Shared() {
if (!g_test_runner)
......@@ -43,7 +41,7 @@ TestRunner& TestRunner::Shared() {
}
void TestRunner::Run(const TestDescriptor& test) {
sky_engine_->RunFromFile(test.path, test.package_root);
sky_engine_->RunFromFile(test.path, test.package_root, "");
}
} // namespace shell
......
......@@ -37,11 +37,9 @@ PlatformImpl* g_platform_impl = nullptr;
using mojo::asset_bundle::ZipAssetBundle;
using mojo::asset_bundle::ZipAssetService;
Engine::Config::Config() {
}
Engine::Config::Config() {}
Engine::Config::~Config() {
}
Engine::Config::~Config() {}
Engine::Engine(const Config& config, rasterizer::RasterizerPtr rasterizer)
: config_(config),
......@@ -49,11 +47,9 @@ Engine::Engine(const Config& config, rasterizer::RasterizerPtr rasterizer)
binding_(this),
activity_running_(false),
have_surface_(false),
weak_factory_(this) {
}
weak_factory_(this) {}
Engine::~Engine() {
}
Engine::~Engine() {}
base::WeakPtr<Engine> Engine::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
......@@ -140,7 +136,7 @@ void Engine::OnViewportMetricsChanged(ViewportMetricsPtr metrics) {
}
void Engine::OnLocaleChanged(const mojo::String& language_code,
const mojo::String& country_code) {
const mojo::String& country_code) {
language_code_ = language_code;
country_code_ = country_code;
if (sky_view_)
......@@ -185,13 +181,16 @@ void Engine::RunFromSnapshotStream(
sky_view_->PushRoute(initial_route_);
}
void Engine::ConfigureZipAssetBundle(const mojo::String& path) {
zip_asset_bundle_ = new ZipAssetBundle(base::FilePath(std::string{path}),
base::WorkerPool::GetTaskRunner(true));
ZipAssetService::Create(mojo::GetProxy(&root_bundle_), zip_asset_bundle_);
}
void Engine::RunFromPrecompiledSnapshot(const mojo::String& bundle_path) {
TRACE_EVENT0("flutter", "Engine::RunFromPrecompiledSnapshot");
std::string path_str = bundle_path;
zip_asset_bundle_ = new ZipAssetBundle(
base::FilePath(path_str), base::WorkerPool::GetTaskRunner(true));
ZipAssetService::Create(mojo::GetProxy(&root_bundle_), zip_asset_bundle_);
ConfigureZipAssetBundle(bundle_path);
sky_view_ = blink::SkyView::Create(this);
sky_view_->CreateView("http://localhost");
......@@ -203,8 +202,13 @@ void Engine::RunFromPrecompiledSnapshot(const mojo::String& bundle_path) {
}
void Engine::RunFromFile(const mojo::String& main,
const mojo::String& package_root) {
const mojo::String& package_root,
const mojo::String& bundle) {
TRACE_EVENT0("flutter", "Engine::RunFromFile");
if (bundle.size() != 0) {
// The specification of an FLX bundle is optional.
ConfigureZipAssetBundle(bundle);
}
std::string package_root_str = package_root;
dart_library_provider_.reset(
new DartLibraryProviderFiles(base::FilePath(package_root_str)));
......@@ -213,32 +217,29 @@ void Engine::RunFromFile(const mojo::String& main,
void Engine::RunFromBundle(const mojo::String& path) {
TRACE_EVENT0("flutter", "Engine::RunFromBundle");
std::string path_str = path;
zip_asset_bundle_ = new ZipAssetBundle(
base::FilePath(path_str), base::WorkerPool::GetTaskRunner(true));
ZipAssetService::Create(mojo::GetProxy(&root_bundle_), zip_asset_bundle_);
root_bundle_->GetAsStream(blink::kSnapshotAssetKey,
base::Bind(&Engine::RunFromSnapshotStream,
weak_factory_.GetWeakPtr(), path_str));
ConfigureZipAssetBundle(path);
root_bundle_->GetAsStream(
blink::kSnapshotAssetKey,
base::Bind(&Engine::RunFromSnapshotStream, weak_factory_.GetWeakPtr(),
std::string{path}));
}
void Engine::RunFromBundleAndSnapshot(const mojo::String& bundle_path,
const mojo::String& snapshot_path) {
TRACE_EVENT0("flutter", "Engine::RunFromBundleAndSnapshot");
std::string bundle_path_str = bundle_path;
zip_asset_bundle_ = new ZipAssetBundle(
base::FilePath(bundle_path_str), base::WorkerPool::GetTaskRunner(true));
ZipAssetService::Create(mojo::GetProxy(&root_bundle_), zip_asset_bundle_);
ConfigureZipAssetBundle(bundle_path);
std::string snapshot_path_str = snapshot_path;
zip_asset_bundle_->AddOverlayFile(blink::kSnapshotAssetKey,
base::FilePath(snapshot_path_str));
root_bundle_->GetAsStream(blink::kSnapshotAssetKey,
base::Bind(&Engine::RunFromSnapshotStream,
weak_factory_.GetWeakPtr(),
bundle_path_str));
root_bundle_->GetAsStream(
blink::kSnapshotAssetKey,
base::Bind(&Engine::RunFromSnapshotStream, weak_factory_.GetWeakPtr(),
std::string{bundle_path}));
}
void Engine::PushRoute(const mojo::String& route) {
......@@ -295,8 +296,7 @@ void Engine::FlushRealTimeEvents() {
animator_->FlushRealTimeEvents();
}
void Engine::Render(std::unique_ptr<flow::LayerTree> layer_tree) {
}
void Engine::Render(std::unique_ptr<flow::LayerTree> layer_tree) {}
} // namespace shell
} // namespace sky
......@@ -64,11 +64,12 @@ class Engine : public UIDelegate,
void SetServices(ServicesDataPtr services) override;
void OnViewportMetricsChanged(ViewportMetricsPtr metrics) override;
void OnLocaleChanged(const mojo::String& language_code,
const mojo::String& country_code) override;
const mojo::String& country_code) override;
void OnPointerPacket(pointer::PointerPacketPtr packet) override;
void RunFromFile(const mojo::String& main,
const mojo::String& package_root) override;
const mojo::String& package_root,
const mojo::String& bundle) override;
void RunFromPrecompiledSnapshot(const mojo::String& bundle_path) override;
void RunFromBundle(const mojo::String& path) override;
void RunFromBundleAndSnapshot(const mojo::String& bundle_path,
......@@ -92,6 +93,8 @@ class Engine : public UIDelegate,
void StopAnimator();
void StartAnimatorIfPossible();
void ConfigureZipAssetBundle(const mojo::String& path);
Config config_;
std::unique_ptr<Animator> animator_;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册