diff --git a/DEPS b/DEPS index 624c60e49..222e0beea 100644 --- a/DEPS +++ b/DEPS @@ -54,7 +54,7 @@ deps = { # and not have to specific specific hashes. 'src/lib/ftl': - Var('fuchsia_git') + '/ftl' + '@' + '4917351099cfb11d7bd9a808fd4fce67928c9e40', + Var('fuchsia_git') + '/ftl' + '@' + '5e9935c7205c119ce05098dc1d9c8eaac0595ba4', 'src/lib/tonic': Var('fuchsia_git') + '/tonic' + '@' + '5ca4053563027007ef2e7b2892efe63c26d30259', diff --git a/assets/directory_asset_bundle.cc b/assets/directory_asset_bundle.cc index 9b6c8a42b..035b8f46a 100644 --- a/assets/directory_asset_bundle.cc +++ b/assets/directory_asset_bundle.cc @@ -11,6 +11,7 @@ #include "flutter/glue/data_pipe_utils.h" #include "lib/ftl/files/eintr_wrapper.h" +#include "lib/ftl/files/file.h" #include "lib/ftl/files/path.h" #include "lib/ftl/files/unique_fd.h" @@ -22,13 +23,9 @@ void DirectoryAssetBundle::GetAsStream( mojo::DataPipe pipe; callback.Run(std::move(pipe.consumer_handle)); - std::string asset_path = - files::SimplifyPath(directory_ + "/" + asset_name.get()); - if (asset_path.find(directory_) != 0u) { - FTL_LOG(ERROR) << "Asset name '" << asset_name - << "' attempted to traverse outside asset bundle."; + std::string asset_path = GetPathForAsset(asset_name.get()); + if (asset_path.empty()) return; - } // TODO(abarth): Consider moving the |open| call to task_runner_. ftl::UniqueFD fd(HANDLE_EINTR(open(asset_path.c_str(), O_RDONLY))); @@ -38,6 +35,14 @@ void DirectoryAssetBundle::GetAsStream( task_runner_, [](bool ignored) {}); } +bool DirectoryAssetBundle::GetAsBuffer(const std::string& asset_name, + std::vector* data) { + std::string asset_path = GetPathForAsset(asset_name); + if (asset_path.empty()) + return false; + return files::ReadFileToVector(asset_path, data); +} + DirectoryAssetBundle::~DirectoryAssetBundle() {} DirectoryAssetBundle::DirectoryAssetBundle( @@ -48,4 +53,15 @@ DirectoryAssetBundle::DirectoryAssetBundle( directory_(std::move(directory)), task_runner_(std::move(task_runner)) {} +std::string DirectoryAssetBundle::GetPathForAsset( + const std::string& asset_name) { + std::string asset_path = files::SimplifyPath(directory_ + "/" + asset_name); + if (asset_path.find(directory_) != 0u) { + FTL_LOG(ERROR) << "Asset name '" << asset_name + << "' attempted to traverse outside asset bundle."; + return std::string(); + } + return asset_path; +} + } // namespace blink diff --git a/assets/directory_asset_bundle.h b/assets/directory_asset_bundle.h index 98f90b739..d54a4ab90 100644 --- a/assets/directory_asset_bundle.h +++ b/assets/directory_asset_bundle.h @@ -7,8 +7,8 @@ #include "lib/ftl/macros.h" #include "lib/ftl/tasks/task_runner.h" +#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/environment/async_waiter.h" #include "mojo/services/asset_bundle/interfaces/asset_bundle.mojom.h" @@ -20,6 +20,7 @@ class DirectoryAssetBundle : public mojo::asset_bundle::AssetBundle { DirectoryAssetBundle(mojo::InterfaceRequest request, std::string directory, ftl::RefPtr task_runner); + ~DirectoryAssetBundle() override; // mojo::assert_bundle::AssetBundle implementation: void GetAsStream( @@ -27,10 +28,12 @@ class DirectoryAssetBundle : public mojo::asset_bundle::AssetBundle { const mojo::Callback& callback) override; - private: - ~DirectoryAssetBundle() override; + bool GetAsBuffer(const std::string& asset_name, std::vector* data); - mojo::StrongBinding binding_; + private: + std::string GetPathForAsset(const std::string& asset_name); + + mojo::Binding binding_; const std::string directory_; ftl::RefPtr task_runner_; diff --git a/assets/zip_asset_bundle.h b/assets/zip_asset_bundle.h index cd35bd9d5..30a96191a 100644 --- a/assets/zip_asset_bundle.h +++ b/assets/zip_asset_bundle.h @@ -6,8 +6,8 @@ #define FLUTTER_ASSETS_ZIP_ASSET_BUNDLE_H_ #include "flutter/assets/zip_asset_store.h" +#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/services/asset_bundle/interfaces/asset_bundle.mojom.h" namespace blink { @@ -17,6 +17,7 @@ class ZipAssetBundle : public mojo::asset_bundle::AssetBundle { ZipAssetBundle( mojo::InterfaceRequest request, ftl::RefPtr store); + ~ZipAssetBundle() override; // mojo::assert_bundle::AssetBundle implementation: void GetAsStream( @@ -25,9 +26,7 @@ class ZipAssetBundle : public mojo::asset_bundle::AssetBundle { override; private: - ~ZipAssetBundle() override; - - mojo::StrongBinding binding_; + mojo::Binding binding_; ftl::RefPtr store_; }; diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 2c9a84c5a..47aa1c6f9 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -31,6 +31,8 @@ namespace shell { namespace { +constexpr char kAssetPluginChannel[] = "flutter/assets"; + bool PathExists(const std::string& path) { return access(path.c_str(), R_OK) == 0; } @@ -197,6 +199,9 @@ void Engine::RunFromSnapshotStream( void Engine::ConfigureAssetBundle(const std::string& path) { struct stat stat_result = {0}; + directory_asset_bundle_.reset(); + zip_asset_bundle_.reset(); + if (::stat(path.c_str(), &stat_result) != 0) { LOG(INFO) << "Could not configure asset bundle at path: " << path; return; @@ -204,8 +209,8 @@ void Engine::ConfigureAssetBundle(const std::string& path) { if (S_ISDIR(stat_result.st_mode)) { // Directory asset bundle. - new blink::DirectoryAssetBundle(mojo::GetProxy(&root_bundle_), path, - blink::Threads::IO()); + directory_asset_bundle_ = std::make_unique( + mojo::GetProxy(&root_bundle_), path, blink::Threads::IO()); return; } @@ -213,7 +218,8 @@ void Engine::ConfigureAssetBundle(const std::string& path) { // Zip asset bundle. asset_store_ = ftl::MakeRefCounted( blink::GetUnzipperProviderForPath(path), blink::Threads::IO()); - new blink::ZipAssetBundle(mojo::GetProxy(&root_bundle_), asset_store_); + zip_asset_bundle_ = std::make_unique( + mojo::GetProxy(&root_bundle_), asset_store_); return; } } @@ -365,6 +371,10 @@ void Engine::UpdateSemantics(std::vector update) { void Engine::HandlePlatformMessage( ftl::RefPtr message) { + if (message->name() == kAssetPluginChannel) { + HandleAssetPlatformMessage(std::move(message)); + return; + } blink::Threads::Platform()->PostTask([ platform_view = platform_view_, message = std::move(message) ]() mutable { @@ -373,4 +383,22 @@ void Engine::HandlePlatformMessage( }); } +void Engine::HandleAssetPlatformMessage( + ftl::RefPtr message) { + ftl::RefPtr response = message->response(); + if (!response) + return; + const auto& data = message->data(); + std::string asset_name(reinterpret_cast(data.data()), + data.size()); + std::vector asset_data; + if ((directory_asset_bundle_ && + directory_asset_bundle_->GetAsBuffer(asset_name, &asset_data)) || + (asset_store_ && asset_store_->GetAsBuffer(asset_name, &asset_data))) { + response->Complete(std::move(asset_data)); + } else { + response->CompleteWithError(); + } +} + } // namespace shell diff --git a/shell/common/engine.h b/shell/common/engine.h index ac33bfc18..c7191d6f4 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -23,6 +23,11 @@ #include "mojo/services/asset_bundle/interfaces/asset_bundle.mojom.h" #include "third_party/skia/include/core/SkPicture.h" +namespace blink { +class DirectoryAssetBundle; +class ZipAssetBundle; +} // namespace blink + namespace shell { class PlatformView; class Animator; @@ -97,6 +102,8 @@ class Engine : public sky::SkyEngine, public blink::RuntimeDelegate { void ConfigureAssetBundle(const std::string& path); void ConfigureRuntime(const std::string& script_uri); + void HandleAssetPlatformMessage(ftl::RefPtr message); + ftl::WeakPtr platform_view_; std::unique_ptr animator_; @@ -116,7 +123,10 @@ class Engine : public sky::SkyEngine, public blink::RuntimeDelegate { std::string country_code_; bool semantics_enabled_ = false; mojo::Binding binding_; + ftl::RefPtr asset_store_; + std::unique_ptr directory_asset_bundle_; + std::unique_ptr zip_asset_bundle_; // TODO(eseidel): This should move into an AnimatorStateMachine. bool activity_running_;