提交 6aab8f2c 编写于 作者: A Adam Barth 提交者: GitHub

Add assets plugin (#3151)

This plugin is implemented internally by the engine to integrate with the asset
system.
上级 50870068
......@@ -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',
......
......@@ -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<uint8_t>* 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
......@@ -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<AssetBundle> request,
std::string directory,
ftl::RefPtr<ftl::TaskRunner> 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<void(mojo::ScopedDataPipeConsumerHandle)>& callback)
override;
bool GetAsBuffer(const std::string& asset_name, std::vector<uint8_t>* data);
private:
~DirectoryAssetBundle() override;
std::string GetPathForAsset(const std::string& asset_name);
mojo::StrongBinding<mojo::asset_bundle::AssetBundle> binding_;
mojo::Binding<mojo::asset_bundle::AssetBundle> binding_;
const std::string directory_;
ftl::RefPtr<ftl::TaskRunner> task_runner_;
......
......@@ -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<mojo::asset_bundle::AssetBundle> request,
ftl::RefPtr<ZipAssetStore> 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<mojo::asset_bundle::AssetBundle> binding_;
mojo::Binding<mojo::asset_bundle::AssetBundle> binding_;
ftl::RefPtr<ZipAssetStore> store_;
};
......
......@@ -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<blink::DirectoryAssetBundle>(
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::ZipAssetStore>(
blink::GetUnzipperProviderForPath(path), blink::Threads::IO());
new blink::ZipAssetBundle(mojo::GetProxy(&root_bundle_), asset_store_);
zip_asset_bundle_ = std::make_unique<blink::ZipAssetBundle>(
mojo::GetProxy(&root_bundle_), asset_store_);
return;
}
}
......@@ -365,6 +371,10 @@ void Engine::UpdateSemantics(std::vector<blink::SemanticsNode> update) {
void Engine::HandlePlatformMessage(
ftl::RefPtr<blink::PlatformMessage> 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<blink::PlatformMessage> message) {
ftl::RefPtr<blink::PlatformMessageResponse> response = message->response();
if (!response)
return;
const auto& data = message->data();
std::string asset_name(reinterpret_cast<const char*>(data.data()),
data.size());
std::vector<uint8_t> 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
......@@ -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<blink::PlatformMessage> message);
ftl::WeakPtr<PlatformView> platform_view_;
std::unique_ptr<Animator> animator_;
......@@ -116,7 +123,10 @@ class Engine : public sky::SkyEngine, public blink::RuntimeDelegate {
std::string country_code_;
bool semantics_enabled_ = false;
mojo::Binding<SkyEngine> binding_;
ftl::RefPtr<blink::ZipAssetStore> asset_store_;
std::unique_ptr<blink::DirectoryAssetBundle> directory_asset_bundle_;
std::unique_ptr<blink::ZipAssetBundle> zip_asset_bundle_;
// TODO(eseidel): This should move into an AnimatorStateMachine.
bool activity_running_;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册