From 4ada9803d197c10b29572afe8f6ec72cb7df4a1e Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 3 Jul 2019 16:55:32 -0700 Subject: [PATCH] Add FLEDartProject for macOS embedding Adds an initial version of FLEDartProject, which contains the configuration for running the engine. In the future this will align with FlutterDartProject, and likely share a significant portion of the implementation. This is a breaking change for macOS runners. --- ci/licenses_golden/licenses_flutter | 3 + shell/platform/darwin/macos/BUILD.gn | 3 + .../macos/framework/Headers/FLEDartProject.h | 43 +++++++++++++ .../macos/framework/Headers/FLEEngine.h | 26 ++++---- .../framework/Headers/FLEViewController.h | 13 ++-- .../macos/framework/Headers/FlutterMacOS.h | 1 + .../macos/framework/Source/FLEDartProject.mm | 60 +++++++++++++++++++ .../Source/FLEDartProject_Internal.h | 38 ++++++++++++ .../macos/framework/Source/FLEEngine.mm | 45 +++++++------- .../framework/Source/FLEViewController.mm | 8 +-- 10 files changed, 192 insertions(+), 48 deletions(-) create mode 100644 shell/platform/darwin/macos/framework/Headers/FLEDartProject.h create mode 100644 shell/platform/darwin/macos/framework/Source/FLEDartProject.mm create mode 100644 shell/platform/darwin/macos/framework/Source/FLEDartProject_Internal.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 6d79b2a77d723..8385a8d477749 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -740,6 +740,7 @@ FILE: ../../../flutter/shell/platform/darwin/ios/ios_surface_software.mm FILE: ../../../flutter/shell/platform/darwin/ios/platform_view_ios.h FILE: ../../../flutter/shell/platform/darwin/ios/platform_view_ios.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/FlutterMacOS.podspec +FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FLEDartProject.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FLEEngine.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FLEOpenGLContextHandling.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FLEReshapeListener.h @@ -749,6 +750,8 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterMacO FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterPluginMacOS.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Headers/FlutterPluginRegistrarMacOS.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Info.plist +FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FLEDartProject.mm +FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FLEDartProject_Internal.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FLEEngine.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FLEEngine_Internal.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FLETextInputModel.h diff --git a/shell/platform/darwin/macos/BUILD.gn b/shell/platform/darwin/macos/BUILD.gn index f5bb498a0fb97..a4c3727a49e03 100644 --- a/shell/platform/darwin/macos/BUILD.gn +++ b/shell/platform/darwin/macos/BUILD.gn @@ -33,6 +33,7 @@ _flutter_framework_headers = [ "framework/Headers/FlutterMacOS.h", "framework/Headers/FlutterPluginMacOS.h", "framework/Headers/FlutterPluginRegistrarMacOS.h", + "framework/Headers/FLEDartProject.h", "framework/Headers/FLEEngine.h", "framework/Headers/FLEOpenGLContextHandling.h", "framework/Headers/FLEReshapeListener.h", @@ -49,6 +50,8 @@ shared_library("create_flutter_framework_dylib") { output_name = "$_flutter_framework_name" sources = [ + "framework/Source/FLEDartProject.mm", + "framework/Source/FLEDartProject_Internal.h", "framework/Source/FLEEngine.mm", "framework/Source/FLEEngine_Internal.h", "framework/Source/FLETextInputModel.h", diff --git a/shell/platform/darwin/macos/framework/Headers/FLEDartProject.h b/shell/platform/darwin/macos/framework/Headers/FLEDartProject.h new file mode 100644 index 0000000000000..99ff088af60ef --- /dev/null +++ b/shell/platform/darwin/macos/framework/Headers/FLEDartProject.h @@ -0,0 +1,43 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_FLEDARTPROJECT_H_ +#define FLUTTER_FLEDARTPROJECT_H_ + +#import + +#include "FlutterMacros.h" + +/** + * A set of Flutter and Dart assets used by a `FlutterEngine` to initialize execution. + * + * TODO(stuartmorgan): Align API with FlutterDartProject. + */ +FLUTTER_EXPORT +@interface FLEDartProject : NSObject + +/** + * Initializes a Flutter Dart project from a bundle. + * + * The bundle must either contain a flutter_assets resource directory, or set the Info.plist key + * FLTAssetsPath to override that name (if you are doing a custom build using a different name). + * + * @param bundle The bundle containing the Flutter assets directory. If nil, the main bundle is + * used. + */ +- (nonnull instancetype)initWithBundle:(nullable NSBundle*)bundle NS_DESIGNATED_INITIALIZER; + +/** + * Switches to pass to the Flutter engine. See + * https://github.com/flutter/engine/blob/master/shell/common/switches.h + * for details. Not all switches will apply to embedding mode. + * + * Note: This property is likely to be removed in the future in favor of exposing specific switches + * via their own APIs. + */ +@property(nullable) NSArray* engineSwitches; + +@end + +#endif // FLUTTER_FLEDARTPROJECT_H_ diff --git a/shell/platform/darwin/macos/framework/Headers/FLEEngine.h b/shell/platform/darwin/macos/framework/Headers/FLEEngine.h index 17053caa8ece1..b9b302fcfc23b 100644 --- a/shell/platform/darwin/macos/framework/Headers/FLEEngine.h +++ b/shell/platform/darwin/macos/framework/Headers/FLEEngine.h @@ -7,6 +7,7 @@ #import +#include "FLEDartProject.h" #include "FlutterBinaryMessenger.h" #include "FlutterMacros.h" #include "FlutterPluginRegistrarMacOS.h" @@ -27,22 +28,27 @@ FLUTTER_EXPORT * * @param viewController The view controller associated with this engine. If nil, the engine * will be run headless. + * @param project The project configuration. If nil, a default FLEDartProject will be used. */ -- (nonnull instancetype)initWithViewController:(nullable FLEViewController*)viewController; +- (nonnull instancetype)initWithViewController:(nullable FLEViewController*)viewController + project:(nullable FLEDartProject*)project + NS_DESIGNATED_INITIALIZER; /** - * Launches the Flutter engine with the provided configuration. + * Runs `main()` from this engine's project. * - * @param assets The path to the flutter_assets folder for the Flutter application to be run. - * @param arguments Arguments to pass to the Flutter engine. See - * https://github.com/flutter/engine/blob/master/shell/common/switches.h - * for details. Not all arguments will apply to embedding mode. - * Note: This API layer will abstract arguments in the future, instead of - * providing a direct passthrough. * @return YES if the engine launched successfully. */ -- (BOOL)launchEngineWithAssetsPath:(nonnull NSURL*)assets - commandLineArguments:(nullable NSArray*)arguments; +- (BOOL)run; + +/** + * The `FLEDartProject` associated with this engine. If nil, a default will be used for `run`. + * + * TODO(stuartmorgan): Remove this once FLEViewController takes the project as an initializer + * argument. Blocked on currently needing to create it from a XIB due to the view issues + * described in https://github.com/google/flutter-desktop-embedding/issues/10. + */ +@property(nonatomic, nullable) FLEDartProject* project; /** * The `FLEViewController` associated with this engine, if any. diff --git a/shell/platform/darwin/macos/framework/Headers/FLEViewController.h b/shell/platform/darwin/macos/framework/Headers/FLEViewController.h index 18b5731f98b0f..b127f045d65d4 100644 --- a/shell/platform/darwin/macos/framework/Headers/FLEViewController.h +++ b/shell/platform/darwin/macos/framework/Headers/FLEViewController.h @@ -49,17 +49,12 @@ FLUTTER_EXPORT @property(nonatomic) FlutterMouseTrackingMode mouseTrackingMode; /** - * Launches the Flutter engine with the provided configuration. + * Launches the Flutter engine with the provided project. * - * @param assets The path to the flutter_assets folder for the Flutter application to be run. - * @param arguments Arguments to pass to the Flutter engine. See - * https://github.com/flutter/engine/blob/master/shell/common/switches.h - * for details. Not all arguments will apply to embedding mode. - * Note: This API layer will abstract in the future, instead of providing a direct - * passthrough. + * @param project The project to run in this view controller. If nil, a default `FLEDartProject` + * will be used. * @return YES if the engine launched successfully. */ -- (BOOL)launchEngineWithAssetsPath:(nonnull NSURL*)assets - commandLineArguments:(nullable NSArray*)arguments; +- (BOOL)launchEngineWithProject:(nullable FLEDartProject*)project; @end diff --git a/shell/platform/darwin/macos/framework/Headers/FlutterMacOS.h b/shell/platform/darwin/macos/framework/Headers/FlutterMacOS.h index 317370ea203a1..a2c93777d436e 100644 --- a/shell/platform/darwin/macos/framework/Headers/FlutterMacOS.h +++ b/shell/platform/darwin/macos/framework/Headers/FlutterMacOS.h @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import "FLEDartProject.h" #import "FLEEngine.h" #import "FLEOpenGLContextHandling.h" #import "FLEReshapeListener.h" diff --git a/shell/platform/darwin/macos/framework/Source/FLEDartProject.mm b/shell/platform/darwin/macos/framework/Source/FLEDartProject.mm new file mode 100644 index 0000000000000..49777c7a4203f --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FLEDartProject.mm @@ -0,0 +1,60 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "flutter/shell/platform/darwin/macos/framework/Headers/FLEDartProject.h" +#import "flutter/shell/platform/darwin/macos/framework/Source/FLEDartProject_Internal.h" + +#include + +static NSString* const kICUBundlePath = @"icudtl.dat"; + +@implementation FLEDartProject { + NSBundle* _bundle; +} + +- (instancetype)init { + return [self initWithBundle:nil]; +} + +- (instancetype)initWithBundle:(NSBundle*)bundle { + self = [super init]; + NSAssert(self, @"Super init cannot be nil"); + + _bundle = bundle ?: [NSBundle mainBundle]; + return self; +} + +- (NSString*)assetsPath { + NSString* flutterAssetsName = [_bundle objectForInfoDictionaryKey:@"FLTAssetsPath"]; + if (flutterAssetsName == nil) { + flutterAssetsName = @"flutter_assets"; + } + NSString* path = [_bundle pathForResource:flutterAssetsName ofType:@""]; + if (!path) { + NSLog(@"Failed to find path for \"%@\"", flutterAssetsName); + } + return path; +} + +- (NSString*)ICUDataPath { + NSString* path = [[NSBundle bundleForClass:[self class]] pathForResource:kICUBundlePath + ofType:nil]; + if (!path) { + NSLog(@"Failed to find path for \"%@\"", kICUBundlePath); + } + return path; +} + +- (std::vector)argv { + // FlutterProjectArgs expects a full argv, so when processing it for flags the first item is + // treated as the executable and ignored. Add a dummy value so that all provided arguments + // are used. + std::vector arguments = {"placeholder"}; + for (NSUInteger i = 0; i < _engineSwitches.count; ++i) { + arguments.push_back([_engineSwitches[i] UTF8String]); + } + return arguments; +} + +@end diff --git a/shell/platform/darwin/macos/framework/Source/FLEDartProject_Internal.h b/shell/platform/darwin/macos/framework/Source/FLEDartProject_Internal.h new file mode 100644 index 0000000000000..7063786a7d505 --- /dev/null +++ b/shell/platform/darwin/macos/framework/Source/FLEDartProject_Internal.h @@ -0,0 +1,38 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SHELL_PLATFORM_DARWIN_MACOS_FRAMEWORK_SOURCE_FLEDARTPROJECT_INTERNAL_H_ +#define SHELL_PLATFORM_DARWIN_MACOS_FRAMEWORK_SOURCE_FLEDARTPROJECT_INTERNAL_H_ + +#import "flutter/shell/platform/darwin/macos/framework/Headers/FLEDartProject.h" + +#include + +/** + * Provides access to data needed to construct a FlutterProjectArgs for the project. + */ +@interface FLEDartProject () + +/** + * The path to the Flutter assets directory. + */ +@property(nonatomic, readonly, nullable) NSString* assetsPath; + +/** + * The path to the ICU data file. + */ +@property(nonatomic, readonly, nullable) NSString* ICUDataPath; + +/** + * The command line arguments array for the engine. + * + * WARNING: The pointers in this array are valid only until the next call to set `engineSwitches`. + * The returned vector should be used immediately, then discarded. It is returned this way for + * ease of use with FlutterProjectArgs. + */ +@property(nonatomic, readonly) std::vector argv; + +@end + +#endif // SHELL_PLATFORM_DARWIN_MACOS_FRAMEWORK_SOURCE_FLEDARTPROJECT_INTERNAL_H_ \ No newline at end of file diff --git a/shell/platform/darwin/macos/framework/Source/FLEEngine.mm b/shell/platform/darwin/macos/framework/Source/FLEEngine.mm index 7e26e5fc2b91a..8a60b4f1d17a3 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEEngine.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEEngine.mm @@ -7,11 +7,10 @@ #include +#import "flutter/shell/platform/darwin/macos/framework/Source/FLEDartProject_Internal.h" #import "flutter/shell/platform/darwin/macos/framework/Source/FLEViewController_Internal.h" #import "flutter/shell/platform/embedder/embedder.h" -static NSString* const kICUBundlePath = @"icudtl.dat"; - /** * Private interface declaration for FLEEngine. */ @@ -126,15 +125,18 @@ @implementation FLEEngine { } - (instancetype)init { - return [self initWithViewController:nil]; + return [self initWithViewController:nil project:nil]; } -- (instancetype)initWithViewController:(FLEViewController*)viewController { +- (instancetype)initWithViewController:(FLEViewController*)viewController + project:(FLEDartProject*)project { self = [super init]; - if (self != nil) { - _viewController = viewController; - _messageHandlers = [[NSMutableDictionary alloc] init]; - } + NSAssert(self, @"Super init cannot be nil"); + + _viewController = viewController; + _project = project ?: [[FLEDartProject alloc] init]; + _messageHandlers = [[NSMutableDictionary alloc] init]; + return self; } @@ -144,8 +146,11 @@ - (void)dealloc { } } -- (BOOL)launchEngineWithAssetsPath:(NSURL*)assets - commandLineArguments:(NSArray*)arguments { +- (void)setProject:(FLEDartProject*)project { + _project = project ?: [[FLEDartProject alloc] init]; +} + +- (BOOL)run { if (_engine != NULL) { return NO; } @@ -162,23 +167,13 @@ - (BOOL)launchEngineWithAssetsPath:(NSURL*)assets // TODO(stuartmorgan): Move internal channel registration from FLEViewController to here. - // FlutterProjectArgs is expecting a full argv, so when processing it for flags the first - // item is treated as the executable and ignored. Add a dummy value so that all provided arguments - // are used. - std::vector argv = {"placeholder"}; - for (NSUInteger i = 0; i < arguments.count; ++i) { - argv.push_back([arguments[i] UTF8String]); - } - - NSString* icuData = [[NSBundle bundleForClass:[self class]] pathForResource:kICUBundlePath - ofType:nil]; - FlutterProjectArgs flutterArguments = {}; flutterArguments.struct_size = sizeof(FlutterProjectArgs); - flutterArguments.assets_path = assets.fileSystemRepresentation; - flutterArguments.icu_data_path = icuData.UTF8String; - flutterArguments.command_line_argc = static_cast(argv.size()); - flutterArguments.command_line_argv = &argv[0]; + flutterArguments.assets_path = _project.assetsPath.UTF8String; + flutterArguments.icu_data_path = _project.ICUDataPath.UTF8String; + std::vector arguments = _project.argv; + flutterArguments.command_line_argc = static_cast(arguments.size()); + flutterArguments.command_line_argv = &arguments[0]; flutterArguments.platform_message_callback = (FlutterPlatformMessageCallback)OnPlatformMessage; FlutterEngineResult result = FlutterEngineRun( diff --git a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm index a7872ac9ae55c..4c8d47abcfad8 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm @@ -174,7 +174,7 @@ @implementation FLEViewController { * Performs initialization that's common between the different init paths. */ static void CommonInit(FLEViewController* controller) { - controller->_engine = [[FLEEngine alloc] initWithViewController:controller]; + controller->_engine = [[FLEEngine alloc] initWithViewController:controller project:nil]; controller->_additionalKeyResponders = [[NSMutableOrderedSet alloc] init]; controller->_mouseTrackingMode = FlutterMouseTrackingModeInKeyWindow; } @@ -217,8 +217,7 @@ - (void)setMouseTrackingMode:(FlutterMouseTrackingMode)mode { [self configureTrackingArea]; } -- (BOOL)launchEngineWithAssetsPath:(NSURL*)assets - commandLineArguments:(NSArray*)arguments { +- (BOOL)launchEngineWithProject:(nullable FLEDartProject*)project { // Set up the resource context. This is done here rather than in viewDidLoad as there's no // guarantee that viewDidLoad will be called before the engine is started, and the context must // be valid by that point. @@ -227,7 +226,8 @@ - (BOOL)launchEngineWithAssetsPath:(NSURL*)assets // Register internal plugins before starting the engine. [self addInternalPlugins]; - if (![_engine launchEngineWithAssetsPath:assets commandLineArguments:arguments]) { + _engine.project = project; + if (![_engine run]) { return NO; } // Send the initial user settings such as brightness and text scale factor