• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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