FlutterDartProject.mm 7.3 KB
Newer Older
1 2 3 4
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#define FML_USED_ON_EMBEDDER

7
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h"
8

9 10 11 12
#include "flutter/common/task_runners.h"
#include "flutter/fml/message_loop.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/runtime/dart_vm.h"
13
#include "flutter/shell/common/shell.h"
14
#include "flutter/shell/common/switches.h"
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
#include "flutter/shell/platform/darwin/common/command_line.h"
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"

static const char* kVMKernelSnapshotFileName = "platform.dill";
static const char* kApplicationKernelSnapshotFileName = "kernel_blob.bin";

static blink::Settings DefaultSettingsForProcess() {
  auto command_line = shell::CommandLineFromNSProcessInfo();

  // Settings passed in explicitly via command line arguments take priority.
  auto settings = shell::SettingsFromCommandLine(command_line);

  settings.task_observer_add = [](intptr_t key, fxl::Closure callback) {
    fml::MessageLoop::GetCurrent().AddTaskObserver(key, std::move(callback));
  };

  settings.task_observer_remove = [](intptr_t key) {
    fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
  };

  // The command line arguments may not always be complete. If they aren't, attempt to fill in
  // defaults.

  // 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"];
    if (icuDataPath.length > 0) {
      settings.icu_data_path = icuDataPath.UTF8String;
    }
45 46
  }

47 48 49 50 51 52 53 54 55 56
  if (blink::DartVM::IsRunningPrecompiledCode()) {
    // The application bundle could be specified in the Info.plist.
    if (settings.application_library_path.size() == 0) {
      NSString* libraryName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"FLTLibraryPath"];
      NSString* libraryPath = [[NSBundle mainBundle] pathForResource:libraryName ofType:nil];
      if (libraryPath.length > 0) {
        settings.application_library_path =
            [NSBundle bundleWithPath:libraryPath].executablePath.UTF8String;
      }
    }
57

58 59 60 61 62 63 64 65 66 67 68
    // In case the application bundle is still not specified, look for the App.framework in the
    // Frameworks directory.
    if (settings.application_library_path.size() == 0) {
      NSString* applicationFrameworkPath =
          [[NSBundle mainBundle] pathForResource:@"Frameworks/App.framework" ofType:@""];
      if (applicationFrameworkPath.length > 0) {
        settings.application_library_path =
            [NSBundle bundleWithPath:applicationFrameworkPath].executablePath.UTF8String;
      }
    }
  }
69

70 71
  // Checks to see if the flutter assets directory is already present.
  if (settings.assets_path.size() == 0) {
72 73 74 75 76
    // 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:@""];
77 78 79 80 81 82 83 84 85 86 87

    if (assetsPath.length > 0) {
      settings.assets_path = assetsPath.UTF8String;

      if (!blink::DartVM::IsRunningPrecompiledCode()) {
        {
          // Check if there is a VM kernel snapshot in the assets directory we could potentially
          // use.
          NSURL* vmKernelSnapshotURL = [NSURL URLWithString:@(kVMKernelSnapshotFileName)
                                              relativeToURL:[NSURL fileURLWithPath:assetsPath]];
          if ([[NSFileManager defaultManager] fileExistsAtPath:vmKernelSnapshotURL.path]) {
88
            settings.platform_kernel_path = vmKernelSnapshotURL.path.UTF8String;
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
          }
        }

        {
          // Check if there is an application kernel snapshot in the assets directory we could
          // potentially use.
          NSURL* applicationKernelSnapshotURL =
              [NSURL URLWithString:@(kApplicationKernelSnapshotFileName)
                     relativeToURL:[NSURL fileURLWithPath:assetsPath]];
          if ([[NSFileManager defaultManager] fileExistsAtPath:applicationKernelSnapshotURL.path]) {
            settings.application_kernel_asset = applicationKernelSnapshotURL.path.UTF8String;
          }
        }
      }
    }
  }

  return settings;
107 108
}

109 110 111
@implementation FlutterDartProject {
  fml::scoped_nsobject<NSBundle> _precompiledDartBundle;
  blink::Settings _settings;
112 113
}

114 115 116
#pragma mark - Override base class designated initializers

- (instancetype)init {
117
  return [self initWithFlutterAssets:nil dartMain:nil packages:nil];
118 119 120 121 122 123 124 125
}

#pragma mark - Designated initializers

- (instancetype)initWithPrecompiledDartBundle:(NSBundle*)bundle {
  self = [super init];

  if (self) {
126
    _precompiledDartBundle.reset([bundle retain]);
127

128 129 130 131 132 133 134 135
    _settings = DefaultSettingsForProcess();

    if (bundle != nil) {
      NSString* executablePath = _precompiledDartBundle.get().executablePath;
      if ([[NSFileManager defaultManager] fileExistsAtPath:executablePath]) {
        _settings.application_library_path = executablePath.UTF8String;
      }
    }
136 137 138 139 140
  }

  return self;
}

141 142 143
- (instancetype)initWithFlutterAssets:(NSURL*)flutterAssetsURL
                             dartMain:(NSURL*)dartMainURL
                             packages:(NSURL*)dartPackages {
144 145 146
  self = [super init];

  if (self) {
147
    _settings = DefaultSettingsForProcess();
148

149 150 151 152 153 154 155
    if ([[NSFileManager defaultManager] fileExistsAtPath:dartMainURL.path]) {
      _settings.main_dart_file_path = dartMainURL.path.UTF8String;
    }

    if ([[NSFileManager defaultManager] fileExistsAtPath:dartPackages.path]) {
      _settings.packages_file_path = dartPackages.path.UTF8String;
    }
156 157 158 159 160
  }

  return self;
}

161 162 163
#pragma mark - Convenience initializers

- (instancetype)initFromDefaultSourceForConfiguration {
164 165
  if (blink::DartVM::IsRunningPrecompiledCode()) {
    return [self initWithPrecompiledDartBundle:nil];
166
  } else {
167
    return [self initWithFlutterAssets:nil dartMain:nil packages:nil];
168
  }
169
}
170

171 172 173
- (const blink::Settings&)settings {
  return _settings;
}
174

175 176
- (shell::RunConfiguration)runConfiguration {
  return shell::RunConfiguration::InferFromSettings(_settings);
177 178
}

179 180
#pragma mark - Assets-related utilities

181
+ (NSString*)flutterAssetsName:(NSBundle*)bundle {
182 183 184 185
  NSString* flutterAssetsName = [bundle objectForInfoDictionaryKey:@"FLTAssetsPath"];
  if (flutterAssetsName == nil) {
    // Default to "flutter_assets"
    flutterAssetsName = @"flutter_assets";
186
  }
187 188
  return flutterAssetsName;
}
189

190 191
+ (NSString*)pathForFlutterAssetsFromBundle:(NSBundle*)bundle {
  NSString* flutterAssetsName = [FlutterDartProject flutterAssetsName:bundle];
192
  return [bundle pathForResource:flutterAssetsName ofType:nil];
193 194
}

195
+ (NSString*)lookupKeyForAsset:(NSString*)asset {
196
  NSString* flutterAssetsName = [FlutterDartProject flutterAssetsName:[NSBundle mainBundle]];
197 198 199 200 201 202 203
  return [NSString stringWithFormat:@"%@/%@", flutterAssetsName, asset];
}

+ (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package {
  return [self lookupKeyForAsset:[NSString stringWithFormat:@"packages/%@/%@", package, asset]];
}

204
@end