From 6d617bda1b336c8123d89441bc36034dc306d167 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Tue, 24 Oct 2017 10:22:02 +0200 Subject: [PATCH 1/6] Handle Flutter assets outside FLX --- assets/directory_asset_bundle.h | 2 +- runtime/dart_init.cc | 41 +++++++++++++-- shell/common/engine.cc | 31 +++++++----- shell/common/engine.h | 2 +- shell/common/switches.h | 3 ++ .../android/io/flutter/view/FlutterMain.java | 8 ++- .../io/flutter/view/ResourceExtractor.java | 31 ++++++++++-- .../framework/Headers/FlutterDartProject.h | 9 ++-- .../framework/Source/FlutterDartProject.mm | 50 ++++++++++--------- .../ios/framework/Source/FlutterDartSource.h | 7 +-- .../ios/framework/Source/FlutterDartSource.mm | 16 +++--- 11 files changed, 137 insertions(+), 63 deletions(-) diff --git a/assets/directory_asset_bundle.h b/assets/directory_asset_bundle.h index 0bbe5dc3918f5..75843ea4cd685 100644 --- a/assets/directory_asset_bundle.h +++ b/assets/directory_asset_bundle.h @@ -19,9 +19,9 @@ class DirectoryAssetBundle { bool GetAsBuffer(const std::string& asset_name, std::vector* data); - private: std::string GetPathForAsset(const std::string& asset_name); + private: const std::string directory_; FXL_DISALLOW_COPY_AND_ASSIGN(DirectoryAssetBundle); diff --git a/runtime/dart_init.cc b/runtime/dart_init.cc index 28781864b8bfa..6fa8e3546858e 100644 --- a/runtime/dart_init.cc +++ b/runtime/dart_init.cc @@ -21,6 +21,7 @@ #include #include +#include "flutter/assets/directory_asset_bundle.h" #include "flutter/assets/unzipper_provider.h" #include "flutter/assets/zip_asset_store.h" #include "flutter/common/settings.h" @@ -34,6 +35,7 @@ #include "flutter/runtime/start_up.h" #include "lib/fxl/arraysize.h" #include "lib/fxl/build_config.h" +#include "lib/fxl/files/path.h" #include "lib/fxl/logging.h" #include "lib/fxl/time/time_delta.h" #include "lib/tonic/converter/dart_converter.h" @@ -272,6 +274,16 @@ Dart_Isolate ServiceIsolateCreateCallback(const char* script_uri, #endif // FLUTTER_RUNTIME_MODE } +static bool GetAssetAsBuffer( + const std::string& name, + std::vector* data, + std::unique_ptr& directory_asset_bundle, + fxl::RefPtr& asset_store) { + return (directory_asset_bundle && + directory_asset_bundle->GetAsBuffer(name, data)) || + (asset_store && asset_store->GetAsBuffer(name, data)); +} + Dart_Isolate IsolateCreateCallback(const char* script_uri, const char* main, const char* package_root, @@ -303,11 +315,30 @@ Dart_Isolate IsolateCreateCallback(const char* script_uri, if (!running_from_source) { // Attempt to copy the snapshot from the asset bundle. const std::string& bundle_path = entry_path; - fxl::RefPtr zip_asset_store = - fxl::MakeRefCounted( - GetUnzipperProviderForPath(std::move(bundle_path))); - zip_asset_store->GetAsBuffer(kKernelAssetKey, &kernel_data); - zip_asset_store->GetAsBuffer(kSnapshotAssetKey, &snapshot_data); + + struct stat stat_result = {}; + if (::stat(bundle_path.c_str(), &stat_result) == 0) { + std::unique_ptr directory_asset_bundle; + // TODO(zarah): Remove usage of zip_asset_store once app.flx is removed. + fxl::RefPtr zip_asset_store; + // bundle_path is either the path to app.flx or the flutter assets + // directory. + std::string flx_path = bundle_path; + if (S_ISDIR(stat_result.st_mode)) { + directory_asset_bundle = + std::make_unique(bundle_path); + flx_path = files::GetDirectoryName(bundle_path) + "/app.flx"; + } + + if (access(flx_path.c_str(), R_OK) == 0) { + zip_asset_store = fxl::MakeRefCounted( + GetUnzipperProviderForPath(flx_path)); + } + GetAssetAsBuffer(kKernelAssetKey, &kernel_data, directory_asset_, + zip_asset_store); + GetAssetAsBuffer(kSnapshotAssetKey, &snapshot_data, + directory_asset_bundle, zip_asset_store); + } } } diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 04de8a2b41390..20fb78330b0d9 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -289,9 +289,17 @@ void Engine::Init(const std::string& bundle_path) { #error Unknown OS #endif + std::string flx_path = bundle_path; + struct stat stat_result = {}; + if (::stat(flx_path.c_str(), &stat_result) == 0) { + if (S_ISDIR(stat_result.st_mode)) { + flx_path = files::GetDirectoryName(bundle_path) + "/app.flx"; + } + } + blink::InitRuntime(vm_snapshot_data, vm_snapshot_instr, default_isolate_snapshot_data, - default_isolate_snapshot_instr, bundle_path); + default_isolate_snapshot_instr, flx_path); } const std::string Engine::main_entrypoint_ = "main"; @@ -579,18 +587,18 @@ void Engine::ConfigureAssetBundle(const std::string& path) { return; } + std::string flx_path; if (S_ISDIR(stat_result.st_mode)) { directory_asset_bundle_ = std::make_unique(path); - return; + flx_path = files::GetDirectoryName(path) + "/app.flx"; + } else if (S_ISREG(stat_result.st_mode)) { + flx_path = path; } - if (S_ISREG(stat_result.st_mode)) { + if (PathExists(flx_path)) { asset_store_ = fxl::MakeRefCounted( - blink::GetUnzipperProviderForPath(path)); - directory_asset_bundle_ = std::make_unique( - files::GetDirectoryName(path)); - return; + blink::GetUnzipperProviderForPath(flx_path)); } } @@ -689,12 +697,9 @@ void Engine::HandleAssetPlatformMessage( const auto& data = message->data(); std::string asset_name(reinterpret_cast(data.data()), data.size()); - std::vector asset_data; - if (GetAssetAsBuffer(asset_name, &asset_data)) { - response->Complete(std::move(asset_data)); - } else { - response->CompleteEmpty(); - } + std::string asset_path = directory_asset_bundle_->GetPathForAsset(asset_name); + response->Complete( + std::vector(asset_path.begin(), asset_path.end())); } bool Engine::GetAssetAsBuffer(const std::string& name, diff --git a/shell/common/engine.h b/shell/common/engine.h index 7706b6da50be1..907940d2e027f 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -118,7 +118,7 @@ class Engine : public blink::RuntimeDelegate { std::string country_code_; std::string user_settings_data_; bool semantics_enabled_ = false; - // TODO(abarth): Unify these two behind a common interface. + // TODO(zarah): Remove usage of asset_store_ once app.flx is removed. fxl::RefPtr asset_store_; std::unique_ptr directory_asset_bundle_; // TODO(eseidel): This should move into an AnimatorStateMachine. diff --git a/shell/common/switches.h b/shell/common/switches.h index 2432523dd46ae..6d5bd03a80a72 100644 --- a/shell/common/switches.h +++ b/shell/common/switches.h @@ -62,6 +62,9 @@ DEF_SWITCH(EnableTxt, "enable-txt", "Enable libtxt as the text shaping library instead of Blink.") DEF_SWITCH(FLX, "flx", "Specify the FLX path.") +DEF_SWITCH(FlutterAssetsDir, + "flutter-assets-dir", + "Path to the Flutter assets directory.") DEF_SWITCH(Help, "help", "Display this help text.") DEF_SWITCH(LogTag, "log-tag", "Tag associated with log messages.") DEF_SWITCH(MainDartFile, "dart-main", "The path to the main Dart file.") diff --git a/shell/platform/android/io/flutter/view/FlutterMain.java b/shell/platform/android/io/flutter/view/FlutterMain.java index 20a2121189172..ecbcc3650302a 100644 --- a/shell/platform/android/io/flutter/view/FlutterMain.java +++ b/shell/platform/android/io/flutter/view/FlutterMain.java @@ -38,6 +38,7 @@ public class FlutterMain { private static final String AOT_ISOLATE_SNAPSHOT_INSTR_KEY = "isolate-snapshot-instr"; private static final String FLX_KEY = "flx"; private static final String SNAPSHOT_BLOB_KEY = "snapshot-blob"; + private static final String FLUTTER_ASSETS_DIR_KEY = "flutter-assets-dir"; // XML Attribute keys supported in AndroidManifest.xml public static final String PUBLIC_AOT_AOT_SHARED_LIBRARY_PATH = @@ -54,6 +55,8 @@ public class FlutterMain { FlutterMain.class.getName() + '.' + FLX_KEY; public static final String PUBLIC_SNAPSHOT_BLOB_KEY = FlutterMain.class.getName() + '.' + SNAPSHOT_BLOB_KEY; + public static final String PUBLIC_FLUTTER_ASSETS_DIR_KEY = + FlutterMain.class.getName() + '.' + FLUTTER_ASSETS_DIR_KEY; // Resource names used for components of the precompiled snapshot. private static final String DEFAULT_AOT_SHARED_LIBRARY_PATH= "app.so"; @@ -63,6 +66,7 @@ public class FlutterMain { private static final String DEFAULT_AOT_ISOLATE_SNAPSHOT_INSTR = "isolate_snapshot_instr"; private static final String DEFAULT_FLX = "app.flx"; private static final String DEFAULT_SNAPSHOT_BLOB = "snapshot_blob.bin"; + private static final String DEFAULT_FLUTTER_ASSETS_DIR = "flutter_assets"; private static final String MANIFEST = "flutter.yaml"; @@ -79,6 +83,7 @@ public class FlutterMain { private static String sAotIsolateSnapshotInstr = DEFAULT_AOT_ISOLATE_SNAPSHOT_INSTR; private static String sFlx = DEFAULT_FLX; private static String sSnapshotBlob = DEFAULT_SNAPSHOT_BLOB; + private static String sFlutterAssetsDir = DEFAULT_FLUTTER_ASSETS_DIR; private static boolean sInitialized = false; private static ResourceExtractor sResourceExtractor; @@ -239,6 +244,7 @@ private static void initResources(Context applicationContext) { sResourceExtractor = new ResourceExtractor(context) .addResources(SKY_RESOURCES) .addResource(sFlx); + .addResource(sFlutterAssetsDir) if (sIsPrecompiledAsSharedLibrary) { sResourceExtractor .addResource(sAotSharedLibraryPath); @@ -290,7 +296,7 @@ public static boolean isRunningPrecompiledCode() { public static String findAppBundlePath(Context applicationContext) { String dataDirectory = PathUtils.getDataDirectory(applicationContext); - File appBundle = new File(dataDirectory, sFlx); + File appBundle = new File(dataDirectory, sFlutterAssetsDir); return appBundle.exists() ? appBundle.getPath() : null; } } diff --git a/shell/platform/android/io/flutter/view/ResourceExtractor.java b/shell/platform/android/io/flutter/view/ResourceExtractor.java index d85197a8fa7f0..281f15a716646 100644 --- a/shell/platform/android/io/flutter/view/ResourceExtractor.java +++ b/shell/platform/android/io/flutter/view/ResourceExtractor.java @@ -17,8 +17,10 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.LinkedList; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; @@ -48,12 +50,27 @@ private void extractResources() { try { byte[] buffer = null; final String[] assets = manager.list(""); - for (String asset : assets) { + LinkedList assetList = new LinkedList<>(Arrays.asList(assets)); + while(!assetList.isEmpty()) { + String asset = assetList.pop(); if (!mResources.contains(asset)) continue; + + if (manager.list(asset).length > 0) { + // The asset is a directory + for (String a: manager.list(asset)) { + assetList.add(asset + File.separator + a); + mResources.add(asset + File.separator + a); + } + continue; + } + final File output = new File(dataDir, asset); if (output.exists()) continue; + if (output.getParentFile() != null) { + output.getParentFile().mkdirs(); + } InputStream is = null; OutputStream os = null; try { @@ -179,10 +196,18 @@ public boolean accept(File dir, String name) { private void deleteFiles() { final File dataDir = new File(PathUtils.getDataDirectory(mContext)); - for (String resource : mResources) { + LinkedList files = new LinkedList<>(mResources); + while (!files.isEmpty()) { + String resource = files.pop(); final File file = new File(dataDir, resource); if (file.exists()) { - file.delete(); + if (file.isFile()) { + file.delete(); + } else { + for (String f : file.list()) { + files.add(resource + File.separator + f); + } + } } } for (String timestamp : getExistingTimestamps(dataDir)) { diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h b/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h index 79c7a7a1c9a9a..4da012e8819ef 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h @@ -14,11 +14,12 @@ FLUTTER_EXPORT - (instancetype)initWithPrecompiledDartBundle:(NSBundle*)bundle NS_DESIGNATED_INITIALIZER; -- (instancetype)initWithFLXArchive:(NSURL*)archiveURL - dartMain:(NSURL*)dartMainURL - packages:(NSURL*)dartPackages NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithFlutterAssets:(NSURL*)archiveURL + dartMain:(NSURL*)dartMainURL + packages:(NSURL*)dartPackages NS_DESIGNATED_INITIALIZER; -- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)archiveURL NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithFlutterAssetsWithScriptSnapshot:(NSURL*)archiveURL + NS_DESIGNATED_INITIALIZER; - (instancetype)initFromDefaultSourceForConfiguration; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index e220b326ad063..8d21f0b50d3ea 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -43,7 +43,7 @@ + (void)initialize { #pragma mark - Override base class designated initializers - (instancetype)init { - return [self initWithFLXArchive:nil dartMain:nil packages:nil]; + return [self initWithFlutterAssets:nil dartMain:nil packages:nil]; } #pragma mark - Designated initializers @@ -60,15 +60,15 @@ - (instancetype)initWithPrecompiledDartBundle:(NSBundle*)bundle { return self; } -- (instancetype)initWithFLXArchive:(NSURL*)archiveURL - dartMain:(NSURL*)dartMainURL - packages:(NSURL*)dartPackages { +- (instancetype)initWithFlutterAssets:(NSURL*)flutterAssetsURL + dartMain:(NSURL*)dartMainURL + packages:(NSURL*)dartPackages { self = [super init]; if (self) { _dartSource = [[FlutterDartSource alloc] initWithDartMain:dartMainURL packages:dartPackages - flxArchive:archiveURL]; + flutterAssets:flutterAssetsURL]; [self checkReadiness]; } @@ -76,11 +76,12 @@ - (instancetype)initWithFLXArchive:(NSURL*)archiveURL return self; } -- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)archiveURL { +- (instancetype)initWithFlutterAssetsWithScriptSnapshot:(NSURL*)flutterAssetsURL { self = [super init]; if (self) { - _dartSource = [[FlutterDartSource alloc] initWithFLXArchiveWithScriptSnapshot:archiveURL]; + _dartSource = + [[FlutterDartSource alloc] initWithFlutterAssetsWithScriptSnapshot:flutterAssetsURL]; [self checkReadiness]; } @@ -100,19 +101,19 @@ - (instancetype)initFromDefaultSourceForConfiguration { // Load directly from sources if the appropriate command line flags are // specified. If not, try loading from a script snapshot in the framework // bundle. - NSURL* flxURL = URLForSwitch(shell::FlagForSwitch(shell::Switch::FLX)); + NSURL* flutterAssetsURL = URLForSwitch(shell::FlagForSwitch(shell::Switch::FlutterAssetsDir)); - if (flxURL == nil) { + if (flutterAssetsURL == nil) { // If the URL was not specified on the command line, look inside the // FlutterApplication bundle. - NSString* flxPath = [self pathForFLXFromBundle:bundle]; - if (flxPath != nil) { - flxURL = [NSURL fileURLWithPath:flxPath isDirectory:NO]; + NSString* flutterAssetsPath = [self pathForFlutterAssetsFromBundle:bundle]; + if (flutterAssetsPath != nil) { + flutterAssetsURL = [NSURL fileURLWithPath:flutterAssetsPath isDirectory:NO]; } } - if (flxURL == nil) { - NSLog(@"Error: FLX file not present in bundle; unable to start app."); + if (flutterAssetsURL == nil) { + NSLog(@"Error: flutterAssets directory not present in bundle; unable to start app."); [self release]; return nil; } @@ -120,7 +121,8 @@ - (instancetype)initFromDefaultSourceForConfiguration { NSURL* dartMainURL = URLForSwitch(shell::FlagForSwitch(shell::Switch::MainDartFile)); NSURL* dartPackagesURL = URLForSwitch(shell::FlagForSwitch(shell::Switch::Packages)); - return [self initWithFLXArchive:flxURL dartMain:dartMainURL packages:dartPackagesURL]; + return + [self initWithFlutterAssets:flutterAssetsURL dartMain:dartMainURL packages:dartPackagesURL]; } NSAssert(NO, @"Unreachable"); @@ -142,14 +144,14 @@ - (void)checkReadiness { } } -- (NSString*)pathForFLXFromBundle:(NSBundle*)bundle { - NSString* flxName = [bundle objectForInfoDictionaryKey:@"FLTFlxName"]; - if (flxName == nil) { - // Default to "app.flx" - flxName = @"app"; +- (NSString*)pathForFlutterAssetsFromBundle:(NSBundle*)bundle { + NSString* flutterAssetsName = [bundle objectForInfoDictionaryKey:@"FLTFlxName"]; + if (flutterAssetsName == nil) { + // Default to "flutter_assets" + flutterAssetsName = @"flutter_assets"; } - return [bundle pathForResource:flxName ofType:@"flx"]; + return [bundle pathForResource:flutterAssetsName ofType:nil]; } #pragma mark - Launching the project in a preconfigured engine. @@ -257,10 +259,10 @@ - (void)runFromPrecompiledSourceInEngine:(shell::Engine*)engine return; } - NSString* path = [self pathForFLXFromBundle:_precompiledDartBundle]; + NSString* path = [self pathForFlutterAssetsFromBundle:_precompiledDartBundle]; if (path.length == 0) { NSString* message = [NSString stringWithFormat: - @"Could not find the 'app.flx' archive in " + @"Could not find the 'flutter_assets' dir in " @"the precompiled Dart bundle with ID '%@'", _precompiledDartBundle.bundleIdentifier]; result(NO, message); @@ -293,7 +295,7 @@ - (void)runFromSourceInEngine:(shell::Engine*)engine return result(NO, message); } - std::string bundle_path = _dartSource.flxArchive.absoluteURL.path.UTF8String; + std::string bundle_path = _dartSource.flutterAssets.absoluteURL.path.UTF8String; if (_dartSource.archiveContainsScriptSnapshot) { blink::Threads::UI()->PostTask([ diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartSource.h b/shell/platform/darwin/ios/framework/Source/FlutterDartSource.h index 8cdfc4ab707c2..34ab52931bf81 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartSource.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartSource.h @@ -13,14 +13,15 @@ typedef void (^ValidationResult)(BOOL result, NSString* message); @property(nonatomic, readonly) NSURL* dartMain; @property(nonatomic, readonly) NSURL* packages; -@property(nonatomic, readonly) NSURL* flxArchive; +@property(nonatomic, readonly) NSURL* flutterAssets; @property(nonatomic, readonly) BOOL archiveContainsScriptSnapshot; - (instancetype)initWithDartMain:(NSURL*)dartMain packages:(NSURL*)packages - flxArchive:(NSURL*)flxArchive NS_DESIGNATED_INITIALIZER; + flutterAssets:(NSURL*)flutterAssets NS_DESIGNATED_INITIALIZER; -- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)flxArchive NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithFlutterAssetsWithScriptSnapshot:(NSURL*)flutterAssets + NS_DESIGNATED_INITIALIZER; - (void)validate:(ValidationResult)result; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartSource.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartSource.mm index f7fabea4597fb..1f99c697cac86 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartSource.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartSource.mm @@ -8,26 +8,26 @@ @implementation FlutterDartSource @synthesize dartMain = _dartMain; @synthesize packages = _packages; -@synthesize flxArchive = _flxArchive; +@synthesize flutterAssets = _flutterAssets; @synthesize archiveContainsScriptSnapshot = _archiveContainsScriptSnapshot; #pragma mark - Convenience Initializers - (instancetype)init { - return [self initWithDartMain:nil packages:nil flxArchive:nil]; + return [self initWithDartMain:nil packages:nil flutterAssets:nil]; } #pragma mark - Designated Initializers - (instancetype)initWithDartMain:(NSURL*)dartMain packages:(NSURL*)packages - flxArchive:(NSURL*)flxArchive { + flutterAssets:(NSURL*)flutterAssets { self = [super init]; if (self) { _dartMain = [dartMain copy]; _packages = [packages copy]; - _flxArchive = [flxArchive copy]; + _flutterAssets = [flutterAssets copy]; NSFileManager* fileManager = [NSFileManager defaultManager]; @@ -44,11 +44,11 @@ - (instancetype)initWithDartMain:(NSURL*)dartMain return self; } -- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)flxArchive { +- (instancetype)initWithFlutterAssetsWithScriptSnapshot:(NSURL*)flutterAssets { self = [super init]; if (self) { - _flxArchive = [flxArchive copy]; + _flutterAssets = [flutterAssets copy]; _archiveContainsScriptSnapshot = YES; } @@ -79,7 +79,7 @@ - (void)validate:(ValidationResult)result { BOOL isValid = YES; - isValid &= CheckDartProjectURL(log, _flxArchive, @"FLX archive"); + isValid &= CheckDartProjectURL(log, _flutterAssets, @"Flutter assets"); if (!_archiveContainsScriptSnapshot) { isValid &= CheckDartProjectURL(log, _dartMain, @"Dart main"); @@ -92,7 +92,7 @@ - (void)validate:(ValidationResult)result { - (void)dealloc { [_dartMain release]; [_packages release]; - [_flxArchive release]; + [_flutterAssets release]; [super dealloc]; } From a720c442b3753ba34d779a3276a2cb9b781de7cd Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Tue, 14 Nov 2017 13:42:56 +0100 Subject: [PATCH 2/6] comments --- runtime/dart_init.cc | 2 +- .../io/flutter/view/ResourceExtractor.java | 36 +++++++------------ .../framework/Headers/FlutterDartProject.h | 6 ++++ .../framework/Source/FlutterDartProject.mm | 12 ++++++- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/runtime/dart_init.cc b/runtime/dart_init.cc index 6fa8e3546858e..a221a78ebe6e4 100644 --- a/runtime/dart_init.cc +++ b/runtime/dart_init.cc @@ -334,7 +334,7 @@ Dart_Isolate IsolateCreateCallback(const char* script_uri, zip_asset_store = fxl::MakeRefCounted( GetUnzipperProviderForPath(flx_path)); } - GetAssetAsBuffer(kKernelAssetKey, &kernel_data, directory_asset_, + GetAssetAsBuffer(kKernelAssetKey, &kernel_data, directory_asset_bundle, zip_asset_store); GetAssetAsBuffer(kSnapshotAssetKey, &snapshot_data, directory_asset_bundle, zip_asset_store); diff --git a/shell/platform/android/io/flutter/view/ResourceExtractor.java b/shell/platform/android/io/flutter/view/ResourceExtractor.java index 281f15a716646..0975e089cb273 100644 --- a/shell/platform/android/io/flutter/view/ResourceExtractor.java +++ b/shell/platform/android/io/flutter/view/ResourceExtractor.java @@ -71,31 +71,19 @@ private void extractResources() { if (output.getParentFile() != null) { output.getParentFile().mkdirs(); } - InputStream is = null; - OutputStream os = null; - try { - is = manager.open(asset); - os = new FileOutputStream(output); - if (buffer == null) { - buffer = new byte[BUFFER_SIZE]; - } - - int count = 0; - while ((count = is.read(buffer, 0, BUFFER_SIZE)) != -1) { - os.write(buffer, 0, count); - } - os.flush(); - } finally { - try { - if (is != null) { - is.close(); + try (InputStream is = manager.open(asset)) { + try (OutputStream os = new FileOutputStream(output)) { + if (buffer == null) { + buffer = new byte[BUFFER_SIZE]; + } + + int count = 0; + while ((count = is.read(buffer, 0, BUFFER_SIZE)) != -1) { + os.write(buffer, 0, count); } - } finally { - if (os != null) { - os.close(); - } - } - } + os.flush(); + } + } } } catch (IOException e) { Log.w(TAG, "Exception unpacking resources: " + e.getMessage()); diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h b/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h index 4da012e8819ef..615905bec931d 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h @@ -14,6 +14,12 @@ FLUTTER_EXPORT - (instancetype)initWithPrecompiledDartBundle:(NSBundle*)bundle NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithFLXArchive:(NSURL*)archiveURL + dartMain:(NSURL*)dartMainURL + packages:(NSURL*)dartPackages NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)archiveURL NS_DESIGNATED_INITIALIZER; + - (instancetype)initWithFlutterAssets:(NSURL*)archiveURL dartMain:(NSURL*)dartMainURL packages:(NSURL*)dartPackages NS_DESIGNATED_INITIALIZER; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index 8d21f0b50d3ea..60ba7b81aa77f 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -60,6 +60,16 @@ - (instancetype)initWithPrecompiledDartBundle:(NSBundle*)bundle { return self; } +- (instancetype)initWithFLXArchive:(NSURL*)archiveURL + dartMain:(NSURL*)dartMainURL + packages:(NSURL*)dartPackages { + return nil; +} + +- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)archiveURL { + return nil; +} + - (instancetype)initWithFlutterAssets:(NSURL*)flutterAssetsURL dartMain:(NSURL*)dartMainURL packages:(NSURL*)dartPackages { @@ -145,7 +155,7 @@ - (void)checkReadiness { } - (NSString*)pathForFlutterAssetsFromBundle:(NSBundle*)bundle { - NSString* flutterAssetsName = [bundle objectForInfoDictionaryKey:@"FLTFlxName"]; + NSString* flutterAssetsName = [bundle objectForInfoDictionaryKey:@"FLTAssetsPath"]; if (flutterAssetsName == nil) { // Default to "flutter_assets" flutterAssetsName = @"flutter_assets"; From 834b85c4f4b390fa28efc1d4b3b2575ae6a2add5 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Thu, 23 Nov 2017 15:44:23 +0100 Subject: [PATCH 3/6] fix bug after rebase --- shell/platform/android/io/flutter/view/FlutterMain.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/android/io/flutter/view/FlutterMain.java b/shell/platform/android/io/flutter/view/FlutterMain.java index ecbcc3650302a..0a6783882ac11 100644 --- a/shell/platform/android/io/flutter/view/FlutterMain.java +++ b/shell/platform/android/io/flutter/view/FlutterMain.java @@ -243,8 +243,8 @@ private static void initResources(Context applicationContext) { new ResourceCleaner(context).start(); sResourceExtractor = new ResourceExtractor(context) .addResources(SKY_RESOURCES) - .addResource(sFlx); - .addResource(sFlutterAssetsDir) + .addResource(sFlx) + .addResource(sFlutterAssetsDir); if (sIsPrecompiledAsSharedLibrary) { sResourceExtractor .addResource(sAotSharedLibraryPath); From 2efa7f058113d4082046e8d887d05b8ea4468380 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Fri, 24 Nov 2017 11:29:22 +0100 Subject: [PATCH 4/6] Expect engine to be called with Flutter asset dir --- shell/common/engine.cc | 20 ++++++++++--------- shell/platform/darwin/common/platform_mac.mm | 17 ++++++++-------- .../darwin/desktop/platform_view_mac.mm | 7 ++++--- shell/platform/embedder/embedder.h | 6 +++--- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 20fb78330b0d9..a643f53ab04f2 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -587,18 +587,20 @@ void Engine::ConfigureAssetBundle(const std::string& path) { return; } - std::string flx_path; + if (S_ISREG(stat_result.st_mode)) { + FXL_LOG(INFO) << "Could not configure asset bundle at path: " << path + << ", directory expected."; + return; + } + if (S_ISDIR(stat_result.st_mode)) { directory_asset_bundle_ = std::make_unique(path); - flx_path = files::GetDirectoryName(path) + "/app.flx"; - } else if (S_ISREG(stat_result.st_mode)) { - flx_path = path; - } - - if (PathExists(flx_path)) { - asset_store_ = fxl::MakeRefCounted( - blink::GetUnzipperProviderForPath(flx_path)); + std::string flx_path = files::GetDirectoryName(path) + "/app.flx"; + if (PathExists(flx_path)) { + asset_store_ = fxl::MakeRefCounted( + blink::GetUnzipperProviderForPath(flx_path)); + } } } diff --git a/shell/platform/darwin/common/platform_mac.mm b/shell/platform/darwin/common/platform_mac.mm index f0671955d4348..adfaea7fb0da0 100644 --- a/shell/platform/darwin/common/platform_mac.mm +++ b/shell/platform/darwin/common/platform_mac.mm @@ -115,21 +115,21 @@ bool AttemptLaunchFromCommandLineSwitches(Engine* engine) { const auto& command_line = shell::Shell::Shared().GetCommandLine(); - if (command_line.HasOption(FlagForSwitch(Switch::FLX)) || + if (command_line.HasOption(FlagForSwitch(Switch::FlutterAssetsDir)) || command_line.HasOption(FlagForSwitch(Switch::MainDartFile)) || command_line.HasOption(FlagForSwitch(Switch::Packages))) { - // The main dart file, flx bundle and the package root must be specified in - // one go. We dont want to end up in a situation where we take one value - // from the command line and the others from user defaults. In case, any - // new flags are specified, forget about all the old ones. - [defaults removeObjectForKey:@(FlagForSwitch(Switch::FLX).data())]; + // The main dart file, Flutter assets directory and the package root must be + // specified in one go. We dont want to end up in a situation where we take + // one value from the command line and the others from user defaults. In + // case, any new flags are specified, forget about all the old ones. + [defaults removeObjectForKey:@(FlagForSwitch(Switch::FlutterAssetsDir).data())]; [defaults removeObjectForKey:@(FlagForSwitch(Switch::MainDartFile).data())]; [defaults removeObjectForKey:@(FlagForSwitch(Switch::Packages).data())]; [defaults synchronize]; } - std::string bundle_path = ResolveCommandLineLaunchFlag(FlagForSwitch(Switch::FLX)); + std::string bundle_path = ResolveCommandLineLaunchFlag(FlagForSwitch(Switch::FlutterAssetsDir)); std::string main = ResolveCommandLineLaunchFlag(FlagForSwitch(Switch::MainDartFile)); std::string packages = ResolveCommandLineLaunchFlag(FlagForSwitch(Switch::Packages)); @@ -140,7 +140,8 @@ bool AttemptLaunchFromCommandLineSwitches(Engine* engine) { // Save the newly resolved dart main file and the package root to user // defaults so that the next time the user launches the application in the // simulator without the tooling, the application boots up. - [defaults setObject:@(bundle_path.c_str()) forKey:@(FlagForSwitch(Switch::FLX).data())]; + [defaults setObject:@(bundle_path.c_str()) + forKey:@(FlagForSwitch(Switch::FlutterAssetsDir).data())]; [defaults setObject:@(main.c_str()) forKey:@(FlagForSwitch(Switch::MainDartFile).data())]; [defaults setObject:@(packages.c_str()) forKey:@(FlagForSwitch(Switch::Packages).data())]; diff --git a/shell/platform/darwin/desktop/platform_view_mac.mm b/shell/platform/darwin/desktop/platform_view_mac.mm index ce6ed8d544701..89a1b5c93aed6 100644 --- a/shell/platform/darwin/desktop/platform_view_mac.mm +++ b/shell/platform/darwin/desktop/platform_view_mac.mm @@ -33,14 +33,15 @@ void PlatformViewMac::SetupAndLoadDart() { if (AttemptLaunchFromCommandLineSwitches(&engine())) { - // This attempts launching from an FLX bundle that does not contain a - // dart snapshot. + // This attempts launching from a Flutter assets directory that does not + // contain a dart snapshot. return; } const auto& command_line = shell::Shell::Shared().GetCommandLine(); - std::string bundle_path = command_line.GetOptionValueWithDefault(FlagForSwitch(Switch::FLX), ""); + std::string bundle_path = + command_line.GetOptionValueWithDefault(FlagForSwitch(Switch::FlutterAssetsDir), ""); if (!bundle_path.empty()) { blink::Threads::UI()->PostTask([ engine = engine().GetWeakPtr(), bundle_path ] { if (engine) diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index 96ef4f1048cc6..c4d8f3404caf6 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -105,9 +105,9 @@ typedef void (*FlutterPlatformMessageCallback)( typedef struct { // The size of this struct. Must be sizeof(FlutterProjectArgs). size_t struct_size; - // The path to the FLX file containing project assets. The string can be - // collected after the call to |FlutterEngineRun| returns. The string must be - // NULL terminated. + // The path to the Flutter assets directory containing project assets. The + // string can be collected after the call to |FlutterEngineRun| returns. The + // string must be NULL terminated. const char* assets_path; // The path to the Dart file containing the |main| entry point. The string can // be collected after the call to |FlutterEngineRun| returns. The string must From 7e1815b8c44f05db0b6eb88f3f35e57b0e0a98b1 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Mon, 11 Dec 2017 14:32:18 +0100 Subject: [PATCH 5/6] Added deprecated attributes and reverted asset path change --- shell/common/engine.cc | 30 ++++++++++--------- .../darwin/ios/framework/Headers/Flutter.h | 7 +++++ .../framework/Headers/FlutterDartProject.h | 14 ++++++--- .../framework/Source/FlutterDartProject.mm | 2 +- .../ios/framework/Source/FlutterDartSource.h | 2 +- .../ios/framework/Source/FlutterDartSource.mm | 10 +++---- 6 files changed, 40 insertions(+), 25 deletions(-) diff --git a/shell/common/engine.cc b/shell/common/engine.cc index a643f53ab04f2..44b7e22cc2ee7 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -587,20 +587,18 @@ void Engine::ConfigureAssetBundle(const std::string& path) { return; } - if (S_ISREG(stat_result.st_mode)) { - FXL_LOG(INFO) << "Could not configure asset bundle at path: " << path - << ", directory expected."; - return; - } - + std::string flx_path; if (S_ISDIR(stat_result.st_mode)) { directory_asset_bundle_ = std::make_unique(path); - std::string flx_path = files::GetDirectoryName(path) + "/app.flx"; - if (PathExists(flx_path)) { - asset_store_ = fxl::MakeRefCounted( - blink::GetUnzipperProviderForPath(flx_path)); - } + flx_path = files::GetDirectoryName(path) + "/app.flx"; + } else if (S_ISREG(stat_result.st_mode)) { + flx_path = path; + } + + if (PathExists(flx_path)) { + asset_store_ = fxl::MakeRefCounted( + blink::GetUnzipperProviderForPath(flx_path)); } } @@ -699,9 +697,13 @@ void Engine::HandleAssetPlatformMessage( const auto& data = message->data(); std::string asset_name(reinterpret_cast(data.data()), data.size()); - std::string asset_path = directory_asset_bundle_->GetPathForAsset(asset_name); - response->Complete( - std::vector(asset_path.begin(), asset_path.end())); + + std::vector asset_data; + if (GetAssetAsBuffer(asset_name, &asset_data)) { + response->Complete(std::move(asset_data)); + } else { + response->CompleteEmpty(); + } } bool Engine::GetAssetAsBuffer(const std::string& name, diff --git a/shell/platform/darwin/ios/framework/Headers/Flutter.h b/shell/platform/darwin/ios/framework/Headers/Flutter.h index 87604cf4559c5..839657a5a6758 100644 --- a/shell/platform/darwin/ios/framework/Headers/Flutter.h +++ b/shell/platform/darwin/ios/framework/Headers/Flutter.h @@ -8,6 +8,13 @@ /** BREAKING CHANGES: + December 11, 2017: Deprecated "initWithFLXArchive" and + "initWithFLXArchiveWithScriptSnapshot" and scheculed the same to be marked as + unavailable on January 15, 2018. Instead, "initWithFlutterAssets" and + "initWithFlutterAssetsWithScriptSnapshot" should be used. The reason for this + change is that the FLX archive will be deprecated and replaced with a flutter + assets directory containing the same files as the FLX did. + November 29, 2017: Added a BREAKING CHANGES section. */ diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h b/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h index 615905bec931d..b3a7628363ac8 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h @@ -16,15 +16,21 @@ FLUTTER_EXPORT - (instancetype)initWithFLXArchive:(NSURL*)archiveURL dartMain:(NSURL*)dartMainURL - packages:(NSURL*)dartPackages NS_DESIGNATED_INITIALIZER; + packages:(NSURL*)dartPackages NS_DESIGNATED_INITIALIZER + FLUTTER_DEPRECATED( + "This initializer is no longer used since the FLX will be deprecated. " + "Instead, use [initWithFlutterAssets]."); -- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)archiveURL NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)flutterAssetsURL + NS_DESIGNATED_INITIALIZER FLUTTER_DEPRECATED( + "This initializer is no longer used since the FLX will be deprecated. " + "Instead, use [initWithFlutterAssetsWithScriptSnapshot]."); -- (instancetype)initWithFlutterAssets:(NSURL*)archiveURL +- (instancetype)initWithFlutterAssets:(NSURL*)flutterAssetsURL dartMain:(NSURL*)dartMainURL packages:(NSURL*)dartPackages NS_DESIGNATED_INITIALIZER; -- (instancetype)initWithFlutterAssetsWithScriptSnapshot:(NSURL*)archiveURL +- (instancetype)initWithFlutterAssetsWithScriptSnapshot:(NSURL*)flutterAssetsURL NS_DESIGNATED_INITIALIZER; - (instancetype)initFromDefaultSourceForConfiguration; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index 60ba7b81aa77f..972fb2984356e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -307,7 +307,7 @@ - (void)runFromSourceInEngine:(shell::Engine*)engine std::string bundle_path = _dartSource.flutterAssets.absoluteURL.path.UTF8String; - if (_dartSource.archiveContainsScriptSnapshot) { + if (_dartSource.assetsDirContainsScriptSnapshot) { blink::Threads::UI()->PostTask([ engine = engine->GetWeakPtr(), bundle_path, entrypoint = std::string([entrypoint UTF8String]) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartSource.h b/shell/platform/darwin/ios/framework/Source/FlutterDartSource.h index 34ab52931bf81..c3881ce065185 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartSource.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartSource.h @@ -14,7 +14,7 @@ typedef void (^ValidationResult)(BOOL result, NSString* message); @property(nonatomic, readonly) NSURL* dartMain; @property(nonatomic, readonly) NSURL* packages; @property(nonatomic, readonly) NSURL* flutterAssets; -@property(nonatomic, readonly) BOOL archiveContainsScriptSnapshot; +@property(nonatomic, readonly) BOOL assetsDirContainsScriptSnapshot; - (instancetype)initWithDartMain:(NSURL*)dartMain packages:(NSURL*)packages diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartSource.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartSource.mm index 1f99c697cac86..aecb4e5806b3a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartSource.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartSource.mm @@ -9,7 +9,7 @@ @implementation FlutterDartSource @synthesize dartMain = _dartMain; @synthesize packages = _packages; @synthesize flutterAssets = _flutterAssets; -@synthesize archiveContainsScriptSnapshot = _archiveContainsScriptSnapshot; +@synthesize assetsDirContainsScriptSnapshot = _assetsDirContainsScriptSnapshot; #pragma mark - Convenience Initializers @@ -35,9 +35,9 @@ - (instancetype)initWithDartMain:(NSURL*)dartMain const BOOL packagesExists = [fileManager fileExistsAtPath:packages.absoluteURL.path]; if (!dartMainExists || !packagesExists) { - // We cannot actually verify this without opening up the archive. This is + // We cannot actually verify this without opening up the directory. This is // just an assumption. - _archiveContainsScriptSnapshot = YES; + _assetsDirContainsScriptSnapshot = YES; } } @@ -49,7 +49,7 @@ - (instancetype)initWithFlutterAssetsWithScriptSnapshot:(NSURL*)flutterAssets { if (self) { _flutterAssets = [flutterAssets copy]; - _archiveContainsScriptSnapshot = YES; + _assetsDirContainsScriptSnapshot = YES; } return self; @@ -81,7 +81,7 @@ - (void)validate:(ValidationResult)result { isValid &= CheckDartProjectURL(log, _flutterAssets, @"Flutter assets"); - if (!_archiveContainsScriptSnapshot) { + if (!_assetsDirContainsScriptSnapshot) { isValid &= CheckDartProjectURL(log, _dartMain, @"Dart main"); isValid &= CheckDartProjectURL(log, _packages, @"Dart packages"); } From ece808099bcd23cba04c34891ad3ae5e159f4ae0 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Wed, 13 Dec 2017 10:15:33 +0100 Subject: [PATCH 6/6] parameter name --- .../darwin/ios/framework/Headers/FlutterDartProject.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h b/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h index b3a7628363ac8..9c9c6cd331c36 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h @@ -21,8 +21,8 @@ FLUTTER_EXPORT "This initializer is no longer used since the FLX will be deprecated. " "Instead, use [initWithFlutterAssets]."); -- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)flutterAssetsURL - NS_DESIGNATED_INITIALIZER FLUTTER_DEPRECATED( +- (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)archiveURL NS_DESIGNATED_INITIALIZER + FLUTTER_DEPRECATED( "This initializer is no longer used since the FLX will be deprecated. " "Instead, use [initWithFlutterAssetsWithScriptSnapshot].");