From 48ecfbdde6e4bfa34bf55735fd4205a61b66007a Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Tue, 24 Oct 2017 10:22:02 +0200 Subject: [PATCH 1/5] 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 d40d26f6c1f90..b67e19f1181bb 100644 --- a/runtime/dart_init.cc +++ b/runtime/dart_init.cc @@ -14,6 +14,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" @@ -27,6 +28,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" @@ -253,6 +255,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, @@ -284,11 +296,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 b092ab2addcfc..80fff8531d2de 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -181,9 +181,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"; @@ -460,18 +468,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)); } } @@ -570,12 +578,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 6f7eb7c087989..60d9944c67211 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -116,7 +116,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 176e0b1e9c636..7d4acab55fbff 100644 --- a/shell/common/switches.h +++ b/shell/common/switches.h @@ -61,6 +61,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 a20f65fefc419..71e4ab74ed51f 100644 --- a/shell/platform/android/io/flutter/view/FlutterMain.java +++ b/shell/platform/android/io/flutter/view/FlutterMain.java @@ -37,6 +37,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_VM_SNAPSHOT_DATA_KEY = @@ -51,6 +52,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_VM_SNAPSHOT_DATA = "vm_snapshot_data"; @@ -59,6 +62,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"; @@ -74,6 +78,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; @@ -234,6 +239,7 @@ private static void initResources(Context applicationContext) { .addResource(sAotIsolateSnapshotInstr) .addResource(sFlx) .addResource(sSnapshotBlob) + .addResource(sFlutterAssetsDir) .start(); } @@ -269,7 +275,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 cc66d157ffe93ace167541db01294921f66a5253 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Tue, 14 Nov 2017 13:42:56 +0100 Subject: [PATCH 2/5] 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 b67e19f1181bb..bb840952234ac 100644 --- a/runtime/dart_init.cc +++ b/runtime/dart_init.cc @@ -315,7 +315,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 06f6dd85418fb0d08f0b86cfd7f7e95bbbc01330 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Mon, 20 Nov 2017 08:45:18 +0100 Subject: [PATCH 3/5] Select fonts from asset directory instead of FLX. --- assets/directory_asset_bundle.h | 4 +++- lib/ui/text/font_collection.cc | 12 +++++++----- lib/ui/text/font_collection.h | 6 +++--- runtime/asset_font_selector.cc | 18 +++++++++++------- runtime/asset_font_selector.h | 9 +++++---- shell/common/engine.cc | 13 ++++++------- shell/common/engine.h | 2 +- 7 files changed, 36 insertions(+), 28 deletions(-) diff --git a/assets/directory_asset_bundle.h b/assets/directory_asset_bundle.h index 75843ea4cd685..7c1466d737218 100644 --- a/assets/directory_asset_bundle.h +++ b/assets/directory_asset_bundle.h @@ -9,10 +9,12 @@ #include #include "lib/fxl/macros.h" +#include "lib/fxl/memory/ref_counted.h" namespace blink { -class DirectoryAssetBundle { +class DirectoryAssetBundle + : public fxl::RefCountedThreadSafe { public: explicit DirectoryAssetBundle(std::string directory); ~DirectoryAssetBundle(); diff --git a/lib/ui/text/font_collection.cc b/lib/ui/text/font_collection.cc index d61e8177dbb73..cc47fe061368a 100644 --- a/lib/ui/text/font_collection.cc +++ b/lib/ui/text/font_collection.cc @@ -34,14 +34,15 @@ std::shared_ptr FontCollection::GetFontCollection() const { return collection_; } -void FontCollection::RegisterFontsFromAssetStore( - fxl::RefPtr asset_store) { - if (!asset_store) { +void FontCollection::RegisterFontsFromDirectoryAssetBundle( + fxl::RefPtr directory_asset_bundle) { + if (!directory_asset_bundle) { return; } std::vector manifest_data; - if (!asset_store->GetAsBuffer("FontManifest.json", &manifest_data)) { + if (!directory_asset_bundle->GetAsBuffer("FontManifest.json", + &manifest_data)) { FXL_DLOG(WARNING) << "Could not find the font manifest in the asset store."; return; } @@ -91,7 +92,8 @@ void FontCollection::RegisterFontsFromAssetStore( // TODO: Handle weights and styles. std::vector font_data; - if (asset_store->GetAsBuffer(font_asset->value.GetString(), &font_data)) { + if (directory_asset_bundle->GetAsBuffer(font_asset->value.GetString(), + &font_data)) { // The data must be copied because it needs to be moved into the // typeface as a stream. auto data = diff --git a/lib/ui/text/font_collection.h b/lib/ui/text/font_collection.h index 54eada44da981..e99d6ef9227d8 100644 --- a/lib/ui/text/font_collection.h +++ b/lib/ui/text/font_collection.h @@ -7,7 +7,7 @@ #include #include -#include "flutter/assets/zip_asset_store.h" +#include "flutter/assets/directory_asset_bundle.h" #include "lib/fxl/macros.h" #include "lib/fxl/memory/ref_ptr.h" #include "txt/asset_data_provider.h" @@ -21,8 +21,8 @@ class FontCollection { std::shared_ptr GetFontCollection() const; - void RegisterFontsFromAssetStore( - fxl::RefPtr asset_store); + void RegisterFontsFromDirectoryAssetBundle( + fxl::RefPtr directory_asset_bundle); void RegisterTestFonts(); diff --git a/runtime/asset_font_selector.cc b/runtime/asset_font_selector.cc index 46921ca88e55a..eaa86e3ab9308 100644 --- a/runtime/asset_font_selector.cc +++ b/runtime/asset_font_selector.cc @@ -4,7 +4,7 @@ #include "flutter/runtime/asset_font_selector.h" -#include "flutter/assets/zip_asset_store.h" +#include "flutter/assets/directory_asset_bundle.h" #include "flutter/lib/ui/ui_dart_state.h" #include "flutter/sky/engine/platform/fonts/FontData.h" #include "flutter/sky/engine/platform/fonts/FontFaceCreationParams.h" @@ -80,15 +80,17 @@ struct FontMatcher { } // namespace -void AssetFontSelector::Install(fxl::RefPtr asset_store) { +void AssetFontSelector::Install( + fxl::RefPtr directory_asset_bundle) { RefPtr font_selector = - adoptRef(new AssetFontSelector(std::move(asset_store))); + adoptRef(new AssetFontSelector(std::move(directory_asset_bundle))); font_selector->parseFontManifest(); UIDartState::Current()->set_font_selector(font_selector); } -AssetFontSelector::AssetFontSelector(fxl::RefPtr asset_store) - : asset_store_(std::move(asset_store)) {} +AssetFontSelector::AssetFontSelector( + fxl::RefPtr directory_asset_bundle) + : directory_asset_bundle_(std::move(directory_asset_bundle)) {} AssetFontSelector::~AssetFontSelector() {} @@ -106,7 +108,8 @@ AssetFontSelector::FlutterFontAttributes::~FlutterFontAttributes() {} void AssetFontSelector::parseFontManifest() { std::vector font_manifest_data; - if (!asset_store_->GetAsBuffer(kFontManifestAssetPath, &font_manifest_data)) + if (!directory_asset_bundle_->GetAsBuffer(kFontManifestAssetPath, + &font_manifest_data)) return; rapidjson::Document document; @@ -222,7 +225,8 @@ sk_sp AssetFontSelector::getTypefaceAsset( } std::unique_ptr typeface_asset(new TypefaceAsset); - if (!asset_store_->GetAsBuffer(asset_path, &typeface_asset->data)) { + if (!directory_asset_bundle_->GetAsBuffer(asset_path, + &typeface_asset->data)) { typeface_cache_.insert(std::make_pair(asset_path, nullptr)); return nullptr; } diff --git a/runtime/asset_font_selector.h b/runtime/asset_font_selector.h index a016c0dc64fb7..504973b960aa8 100644 --- a/runtime/asset_font_selector.h +++ b/runtime/asset_font_selector.h @@ -8,7 +8,7 @@ #include #include -#include "flutter/assets/zip_asset_store.h" +#include "flutter/assets/directory_asset_bundle.h" #include "flutter/sky/engine/platform/fonts/FontCacheKey.h" #include "flutter/sky/engine/platform/fonts/FontSelector.h" #include "flutter/sky/engine/platform/fonts/SimpleFontData.h" @@ -23,7 +23,7 @@ class AssetFontSelector : public FontSelector { ~AssetFontSelector() override; - static void Install(fxl::RefPtr asset_store); + static void Install(fxl::RefPtr directory_asset_bundle); PassRefPtr getFontData(const FontDescription& font_description, const AtomicString& family_name) override; @@ -39,14 +39,15 @@ class AssetFontSelector : public FontSelector { private: struct TypefaceAsset; - explicit AssetFontSelector(fxl::RefPtr asset_store); + explicit AssetFontSelector( + fxl::RefPtr directory_asset_bundle); void parseFontManifest(); sk_sp getTypefaceAsset(const FontDescription& font_description, const AtomicString& family_name); - fxl::RefPtr asset_store_; + fxl::RefPtr directory_asset_bundle_; HashMap> font_family_map_; diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 80fff8531d2de..664500488a26a 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -459,8 +459,7 @@ void Engine::SetSemanticsEnabled(bool enabled) { void Engine::ConfigureAssetBundle(const std::string& path) { struct stat stat_result = {}; - directory_asset_bundle_.reset(); - // TODO(abarth): We should reset asset_store_ as well, but that might break + // TODO(abarth): We should reset directory_asset_bundle_, but that might break // custom font loading in hot reload. if (::stat(path.c_str(), &stat_result) != 0) { @@ -471,7 +470,7 @@ void Engine::ConfigureAssetBundle(const std::string& path) { std::string flx_path; if (S_ISDIR(stat_result.st_mode)) { directory_asset_bundle_ = - std::make_unique(path); + fxl::MakeRefCounted(path); flx_path = files::GetDirectoryName(path) + "/app.flx"; } else if (S_ISREG(stat_result.st_mode)) { flx_path = path; @@ -503,11 +502,11 @@ void Engine::DidCreateMainIsolate(Dart_Isolate isolate) { blink::TestFontSelector::Install(); if (!blink::Settings::Get().using_blink) blink::FontCollection::ForProcess().RegisterTestFonts(); - } else if (asset_store_) { - blink::AssetFontSelector::Install(asset_store_); + } else if (directory_asset_bundle_) { + blink::AssetFontSelector::Install(directory_asset_bundle_); if (!blink::Settings::Get().using_blink) { - blink::FontCollection::ForProcess().RegisterFontsFromAssetStore( - asset_store_); + blink::FontCollection::ForProcess().RegisterFontsFromDirectoryAssetBundle( + directory_asset_bundle_); } } } diff --git a/shell/common/engine.h b/shell/common/engine.h index 60d9944c67211..49690b297590d 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -118,7 +118,7 @@ class Engine : public blink::RuntimeDelegate { bool semantics_enabled_ = false; // TODO(zarah): Remove usage of asset_store_ once app.flx is removed. fxl::RefPtr asset_store_; - std::unique_ptr directory_asset_bundle_; + fxl::RefPtr directory_asset_bundle_; // TODO(eseidel): This should move into an AnimatorStateMachine. bool activity_running_; bool have_surface_; From 70492fe28e0758f73cbea2e44ea963eae095cebc Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Tue, 24 Oct 2017 10:22:02 +0200 Subject: [PATCH 4/5] 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 db4b093149904..918195501db34 100644 --- a/runtime/dart_init.cc +++ b/runtime/dart_init.cc @@ -14,6 +14,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" @@ -27,6 +28,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" @@ -265,6 +267,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, @@ -296,11 +308,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 6bb5977ac13bc..b72090db02ef1 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -201,9 +201,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"; @@ -485,18 +493,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)); } } @@ -595,12 +603,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 6f7eb7c087989..60d9944c67211 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -116,7 +116,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 f4af7a06245f802cf17e4f52db48ac8e3b249f27 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Tue, 14 Nov 2017 13:42:56 +0100 Subject: [PATCH 5/5] 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 918195501db34..e387a810cf72e 100644 --- a/runtime/dart_init.cc +++ b/runtime/dart_init.cc @@ -327,7 +327,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";