Skip to content

Commit

Permalink
Add assets plugin (flutter#3151)
Browse files Browse the repository at this point in the history
This plugin is implemented internally by the engine to integrate with the asset
system.
  • Loading branch information
abarth authored Oct 19, 2016
1 parent 5087006 commit 6aab8f2
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 17 deletions.
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
28 changes: 22 additions & 6 deletions assets/directory_asset_bundle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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)));
Expand All @@ -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(
Expand All @@ -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
9 changes: 6 additions & 3 deletions assets/directory_asset_bundle.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -20,17 +20,20 @@ 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(
const mojo::String& asset_name,
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_;

Expand Down
7 changes: 3 additions & 4 deletions assets/zip_asset_bundle.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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(
Expand All @@ -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_;
};

Expand Down
34 changes: 31 additions & 3 deletions shell/common/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -197,23 +199,27 @@ 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;
}

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;
}

if (S_ISREG(stat_result.st_mode)) {
// 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;
}
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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
10 changes: 10 additions & 0 deletions shell/common/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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_;

Expand All @@ -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_;
Expand Down

0 comments on commit 6aab8f2

Please sign in to comment.