From b340b332a1b2c49b5846c26f2d301cf6738fd0e6 Mon Sep 17 00:00:00 2001 From: James Lin Date: Fri, 27 Jul 2018 14:52:41 -0700 Subject: [PATCH 1/2] Don't require `FLTLibraryPath` and `FLTAssetsPath` from the main `NSBundle` We'd like the ability to add Flutter to existing iOS applications without requiring that they set `FLTLibraryPath` and `FLTAssetsPath` in the main bundle's `Info.plist`. Modify `-[FlutterDartProject initWithPrecompiledDartBundle:]` to support setting the library and assets path from the specified `NSBundle` instead. Also remove `+[FlutterDartProject pathForFlutterAssetsFromBundle:]` because we don't use it internally, and it isn't exposed in the header file. --- .../framework/Source/FlutterDartProject.mm | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index a2f561ce69a4a..26bf70d455614 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -19,10 +19,21 @@ static const char* kVMKernelSnapshotFileName = "platform.dill"; static const char* kApplicationKernelSnapshotFileName = "kernel_blob.bin"; -static blink::Settings DefaultSettingsForProcess() { +static blink::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) { auto command_line = shell::CommandLineFromNSProcessInfo(); - // Settings passed in explicitly via command line arguments take priority. + // Precedence: + // 1. Settings from the specified NSBundle. + // 2. Settings passed explicitly via command-line arguments. + // 3. Default values. + + NSBundle* mainBundle = [NSBundle mainBundle]; + NSBundle* engineBundle = [NSBundle bundleForClass:[FlutterViewController class]]; + bool hasExplicitBundle = bundle != nil; + if (bundle == nil) { + bundle = mainBundle; + } + auto settings = shell::SettingsFromCommandLine(command_line); settings.task_observer_add = [](intptr_t key, fml::closure callback) { @@ -38,18 +49,24 @@ // Flutter ships the ICU data file in the the bundle of the engine. Look for it there. if (settings.icu_data_path.size() == 0) { - NSBundle* bundle = [NSBundle bundleForClass:[FlutterViewController class]]; - NSString* icuDataPath = [bundle pathForResource:@"icudtl" ofType:@"dat"]; + NSString* icuDataPath = [engineBundle pathForResource:@"icudtl" ofType:@"dat"]; if (icuDataPath.length > 0) { settings.icu_data_path = icuDataPath.UTF8String; } } if (blink::DartVM::IsRunningPrecompiledCode()) { - // The application bundle could be specified in the Info.plist. + if (hasExplicitBundle) { + NSString* executablePath = bundle.executablePath; + if ([[NSFileManager defaultManager] fileExistsAtPath:executablePath]) { + settings.application_library_path = executablePath.UTF8String; + } + } + + // No application bundle specified. Try a known location from the main bundle's Info.plist. if (settings.application_library_path.size() == 0) { - NSString* libraryName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"FLTLibraryPath"]; - NSString* libraryPath = [[NSBundle mainBundle] pathForResource:libraryName ofType:nil]; + NSString* libraryName = [mainBundle objectForInfoDictionaryKey:@"FLTLibraryPath"]; + NSString* libraryPath = [mainBundle pathForResource:libraryName ofType:@""]; if (libraryPath.length > 0) { settings.application_library_path = [NSBundle bundleWithPath:libraryPath].executablePath.UTF8String; @@ -60,7 +77,7 @@ // Frameworks directory. if (settings.application_library_path.size() == 0) { NSString* applicationFrameworkPath = - [[NSBundle mainBundle] pathForResource:@"Frameworks/App.framework" ofType:@""]; + [mainBundle pathForResource:@"Frameworks/App.framework" ofType:@""]; if (applicationFrameworkPath.length > 0) { settings.application_library_path = [NSBundle bundleWithPath:applicationFrameworkPath].executablePath.UTF8String; @@ -70,11 +87,8 @@ // Checks to see if the flutter assets directory is already present. if (settings.assets_path.size() == 0) { - // The kernel assets will not be present in the Flutter frameworks bundle since it is not user - // editable. Instead, look inside the main bundle. - NSBundle* bundle = [NSBundle mainBundle]; - NSString* assets_directory_name = [FlutterDartProject flutterAssetsName:bundle]; - NSString* assetsPath = [bundle pathForResource:assets_directory_name ofType:@""]; + NSString* assetsName = [FlutterDartProject flutterAssetsName:bundle]; + NSString* assetsPath = [mainBundle pathForResource:assetsName ofType:@""]; if (assetsPath.length > 0) { settings.assets_path = assetsPath.UTF8String; @@ -136,15 +150,7 @@ - (instancetype)initWithPrecompiledDartBundle:(NSBundle*)bundle { if (self) { _precompiledDartBundle.reset([bundle retain]); - - _settings = DefaultSettingsForProcess(); - - if (bundle != nil) { - NSString* executablePath = _precompiledDartBundle.get().executablePath; - if ([[NSFileManager defaultManager] fileExistsAtPath:executablePath]) { - _settings.application_library_path = executablePath.UTF8String; - } - } + _settings = DefaultSettingsForProcess(bundle); } return self; @@ -218,11 +224,6 @@ + (NSString*)flutterAssetsName:(NSBundle*)bundle { return flutterAssetsName; } -+ (NSString*)pathForFlutterAssetsFromBundle:(NSBundle*)bundle { - NSString* flutterAssetsName = [FlutterDartProject flutterAssetsName:bundle]; - return [bundle pathForResource:flutterAssetsName ofType:nil]; -} - + (NSString*)lookupKeyForAsset:(NSString*)asset { NSString* flutterAssetsName = [FlutterDartProject flutterAssetsName:[NSBundle mainBundle]]; return [NSString stringWithFormat:@"%@/%@", flutterAssetsName, asset]; From bcb05c905a45516fd9387a6f89550e902e9460b4 Mon Sep 17 00:00:00 2001 From: James Lin Date: Mon, 13 Aug 2018 13:44:54 -0700 Subject: [PATCH 2/2] Look for an io.flutter.flutter.app NSBundle before falling back to the main NSBundle --- .../darwin/ios/framework/Headers/FlutterDartProject.h | 6 ++++++ .../darwin/ios/framework/Source/FlutterDartProject.mm | 11 ++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h b/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h index f7ece6cf8d71b..08e7cea2e4f0e 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h @@ -43,6 +43,12 @@ FLUTTER_EXPORT */ + (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package; +/** + Returns the default identifier for the bundle where we expect to find the Flutter Dart + application. + */ ++ (NSString*)defaultBundleIdentifier; + @end #endif // FLUTTER_FLUTTERDARTPROJECT_H_ diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index 26bf70d455614..f2b497f9326f3 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -25,11 +25,16 @@ // Precedence: // 1. Settings from the specified NSBundle. // 2. Settings passed explicitly via command-line arguments. - // 3. Default values. + // 3. Settings from the NSBundle with the default bundle ID. + // 4. Settings from the main NSBundle and default values. NSBundle* mainBundle = [NSBundle mainBundle]; NSBundle* engineBundle = [NSBundle bundleForClass:[FlutterViewController class]]; + bool hasExplicitBundle = bundle != nil; + if (bundle == nil) { + bundle = [NSBundle bundleWithIdentifier:[FlutterDartProject defaultBundleIdentifier]]; + } if (bundle == nil) { bundle = mainBundle; } @@ -233,4 +238,8 @@ + (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package { return [self lookupKeyForAsset:[NSString stringWithFormat:@"packages/%@/%@", package, asset]]; } ++ (NSString*)defaultBundleIdentifier { + return @"io.flutter.flutter.app"; +} + @end