1// Copyright 2013 The Flutter Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#define FML_USED_ON_EMBEDDER 6 7#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h" 8 9#include "flutter/common/task_runners.h" 10#include "flutter/fml/message_loop.h" 11#include "flutter/fml/platform/darwin/scoped_nsobject.h" 12#include "flutter/shell/common/shell.h" 13#include "flutter/shell/common/switches.h" 14#include "flutter/shell/platform/darwin/common/command_line.h" 15#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" 16 17extern "C" { 18#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG 19// Used for debugging dart:* sources. 20extern const uint8_t kPlatformStrongDill[]; 21extern const intptr_t kPlatformStrongDillSize; 22#endif 23} 24 25static const char* kApplicationKernelSnapshotFileName = "kernel_blob.bin"; 26 27static flutter::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) { 28 auto command_line = flutter::CommandLineFromNSProcessInfo(); 29 30 // Precedence: 31 // 1. Settings from the specified NSBundle. 32 // 2. Settings passed explicitly via command-line arguments. 33 // 3. Settings from the NSBundle with the default bundle ID. 34 // 4. Settings from the main NSBundle and default values. 35 36 NSBundle* mainBundle = [NSBundle mainBundle]; 37 NSBundle* engineBundle = [NSBundle bundleForClass:[FlutterViewController class]]; 38 39 bool hasExplicitBundle = bundle != nil; 40 if (bundle == nil) { 41 bundle = [NSBundle bundleWithIdentifier:[FlutterDartProject defaultBundleIdentifier]]; 42 } 43 if (bundle == nil) { 44 bundle = mainBundle; 45 } 46 47 auto settings = flutter::SettingsFromCommandLine(command_line); 48 49 settings.task_observer_add = [](intptr_t key, fml::closure callback) { 50 fml::MessageLoop::GetCurrent().AddTaskObserver(key, std::move(callback)); 51 }; 52 53 settings.task_observer_remove = [](intptr_t key) { 54 fml::MessageLoop::GetCurrent().RemoveTaskObserver(key); 55 }; 56 57 // The command line arguments may not always be complete. If they aren't, attempt to fill in 58 // defaults. 59 60 // Flutter ships the ICU data file in the the bundle of the engine. Look for it there. 61 if (settings.icu_data_path.size() == 0) { 62 NSString* icuDataPath = [engineBundle pathForResource:@"icudtl" ofType:@"dat"]; 63 if (icuDataPath.length > 0) { 64 settings.icu_data_path = icuDataPath.UTF8String; 65 } 66 } 67 68 // Checks to see if the flutter assets directory is already present. 69 if (settings.assets_path.size() == 0) { 70 NSString* assetsName = [FlutterDartProject flutterAssetsName:bundle]; 71 NSString* assetsPath = [bundle pathForResource:assetsName ofType:@""]; 72 73 if (assetsPath.length == 0) { 74 assetsPath = [mainBundle pathForResource:assetsName ofType:@""]; 75 } 76 77 if (assetsPath.length == 0) { 78 NSLog(@"Failed to find assets path for \"%@\"", assetsName); 79 } else { 80 settings.assets_path = assetsPath.UTF8String; 81 } 82 } 83 84#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG 85 // There are no ownership concerns here as all mappings are owned by the 86 // embedder and not the engine. 87 auto make_mapping_callback = [](const uint8_t* mapping, size_t size) { 88 return [mapping, size]() { return std::make_unique<fml::NonOwnedMapping>(mapping, size); }; 89 }; 90 91 settings.dart_library_sources_kernel = 92 make_mapping_callback(kPlatformStrongDill, kPlatformStrongDillSize); 93#endif // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG 94 95 return settings; 96} 97 98@implementation FlutterDartProject { 99 fml::scoped_nsobject<NSBundle> _precompiledDartBundle; 100 flutter::Settings _settings; 101} 102 103#pragma mark - Override base class designated initializers 104 105- (instancetype)init { 106 return [self initWithPrecompiledDartBundle:nil]; 107} 108 109#pragma mark - Designated initializers 110 111- (instancetype)initWithPrecompiledDartBundle:(NSBundle*)bundle { 112 self = [super init]; 113 114 if (self) { 115 _precompiledDartBundle.reset([bundle retain]); 116 _settings = DefaultSettingsForProcess(bundle); 117 } 118 119 return self; 120} 121 122#pragma mark - Settings accessors 123 124- (const flutter::Settings&)settings { 125 return _settings; 126} 127 128- (flutter::RunConfiguration)runConfiguration { 129 return [self runConfigurationForEntrypoint:nil]; 130} 131 132- (flutter::RunConfiguration)runConfigurationForEntrypoint:(NSString*)entrypointOrNil { 133 return [self runConfigurationForEntrypoint:entrypointOrNil libraryOrNil:nil]; 134} 135 136- (flutter::RunConfiguration)runConfigurationForEntrypoint:(NSString*)entrypointOrNil 137 libraryOrNil:(NSString*)dartLibraryOrNil { 138 flutter::RunConfiguration config; 139 return config; 140} 141 142#pragma mark - Assets-related utilities 143 144+ (NSString*)flutterAssetsName:(NSBundle*)bundle { 145 if (bundle == nil) { 146 bundle = [NSBundle bundleWithIdentifier:[FlutterDartProject defaultBundleIdentifier]]; 147 } 148 if (bundle == nil) { 149 bundle = [NSBundle mainBundle]; 150 } 151 NSString* flutterAssetsName = [bundle objectForInfoDictionaryKey:@"FLTAssetsPath"]; 152 if (flutterAssetsName == nil) { 153 flutterAssetsName = @"Frameworks/App.framework/flutter_assets"; 154 } 155 return flutterAssetsName; 156} 157 158+ (NSString*)lookupKeyForAsset:(NSString*)asset { 159 return [self lookupKeyForAsset:asset fromBundle:nil]; 160} 161 162+ (NSString*)lookupKeyForAsset:(NSString*)asset fromBundle:(NSBundle*)bundle { 163 NSString* flutterAssetsName = [FlutterDartProject flutterAssetsName:bundle]; 164 return [NSString stringWithFormat:@"%@/%@", flutterAssetsName, asset]; 165} 166 167+ (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package { 168 return [self lookupKeyForAsset:asset fromPackage:package fromBundle:nil]; 169} 170 171+ (NSString*)lookupKeyForAsset:(NSString*)asset 172 fromPackage:(NSString*)package 173 fromBundle:(NSBundle*)bundle { 174 return [self lookupKeyForAsset:[NSString stringWithFormat:@"packages/%@/%@", package, asset] 175 fromBundle:bundle]; 176} 177 178+ (NSString*)defaultBundleIdentifier { 179 return @"io.flutter.flutter.app"; 180} 181 182@end 183