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

Add asset bundle support on Fuchsia (#3005)

After this patch, Flutter apps on Fuchsia can access their asset
bundles. Unlike other platforms, the asset bundles are stored in memory
rather than in the file system.
上级 ca17c1cf
......@@ -24,9 +24,11 @@ executable("content_handler") {
deps = [
"//dart/runtime:libdart",
"//dart/runtime/vm:libdart_platform",
"//flutter/assets",
"//flutter/common",
"//flutter/flow",
"//flutter/glue",
"//flutter/lib/ui",
"//flutter/runtime",
"//flutter/services/engine:interfaces",
"//flutter/services/pointer:interfaces",
......@@ -38,6 +40,7 @@ executable("content_handler") {
"//mojo/public/cpp/system",
"//mojo/public/cpp/utility",
"//mojo/public/interfaces/application",
"//mojo/services/asset_bundle/interfaces",
"//mojo/services/content_handler/interfaces",
"//mojo/services/framebuffer/interfaces",
"//mojo/system",
......
......@@ -13,16 +13,6 @@
#include "mojo/public/cpp/application/connect.h"
namespace flutter_content_handler {
namespace {
constexpr char kSnapshotKey[] = "snapshot_blob.bin";
std::vector<char> ExtractSnapshot(std::vector<char> bundle) {
zip::Unzipper unzipper(std::move(bundle));
return unzipper.Extract(kSnapshotKey);
}
} // namespace
ApplicationImpl::ApplicationImpl(
mojo::InterfaceRequest<mojo::Application> application,
......@@ -32,13 +22,11 @@ ApplicationImpl::ApplicationImpl(
// but we should do that work asynchronously instead. However, there when I
// tried draining the data pipe asynchronously, the drain didn't complete.
// We'll need to investigate why in more detail.
std::vector<char> bundle;
bool result = mtl::BlockingCopyToVector(std::move(response->body), &bundle);
bool result = mtl::BlockingCopyToVector(std::move(response->body), &bundle_);
if (!result) {
FTL_LOG(ERROR) << "Failed to receive bundle.";
return;
}
snapshot_ = ExtractSnapshot(std::move(bundle));
// TODO(abarth): In principle, we should call StartRuntimeIfReady() here but
// because we're draining the data pipe synchronously, we know that we can't
// possibly be ready yet because we haven't received the Initialize() message.
......@@ -69,9 +57,9 @@ void ApplicationImpl::RequestQuit() {
}
void ApplicationImpl::StartRuntimeIfReady() {
if (!runtime_holder_ || snapshot_.empty())
if (!runtime_holder_ || bundle_.empty())
return;
runtime_holder_->Run(url_, std::move(snapshot_));
runtime_holder_->Run(url_, std::move(bundle_));
}
} // namespace flutter_content_handler
......@@ -39,7 +39,7 @@ class ApplicationImpl : public mojo::Application {
mojo::StrongBinding<mojo::Application> binding_;
std::unique_ptr<glue::DrainDataPipeJob> drainer_;
std::vector<char> snapshot_;
std::vector<char> bundle_;
mojo::ShellPtr shell_;
std::string url_;
......
......@@ -6,19 +6,23 @@
#include <utility>
#include "flutter/assets/zip_asset_bundle.h"
#include "flutter/common/threads.h"
#include "flutter/content_handler/rasterizer.h"
#include "flutter/lib/ui/mojo_services.h"
#include "flutter/runtime/dart_controller.h"
#include "flutter/services/engine/sky_engine.mojom.h"
#include "lib/ftl/functional/make_copyable.h"
#include "lib/ftl/functional/make_runnable.h"
#include "lib/ftl/logging.h"
#include "lib/ftl/time/time_delta.h"
#include "lib/zip/create_unzipper.h"
#include "mojo/public/cpp/application/connect.h"
namespace flutter_content_handler {
namespace {
constexpr char kSnapshotKey[] = "snapshot_blob.bin";
constexpr int kPipelineDepth = 3;
constexpr ftl::TimeDelta kTargetFrameInterval =
ftl::TimeDelta::FromMilliseconds(16);
......@@ -49,12 +53,20 @@ void RuntimeHolder::Init(mojo::ApplicationConnectorPtr connector) {
}
void RuntimeHolder::Run(const std::string& script_uri,
std::vector<char> snapshot) {
std::vector<char> bundle) {
InitRootBundle(std::move(bundle));
std::vector<uint8_t> snapshot;
if (!asset_store_->GetAsBuffer(kSnapshotKey, &snapshot)) {
FTL_LOG(ERROR) << "Unable to load snapshot from root bundle.";
return;
}
runtime_ = blink::RuntimeController::Create(this);
runtime_->CreateDartController(script_uri);
runtime_->SetViewportMetrics(viewport_metrics_);
runtime_->dart_controller()->RunFromSnapshot(
reinterpret_cast<const uint8_t*>(snapshot.data()), snapshot.size());
runtime_->dart_controller()->RunFromSnapshot(snapshot.data(),
snapshot.size());
}
void RuntimeHolder::ScheduleFrame() {
......@@ -89,6 +101,30 @@ void RuntimeHolder::Render(std::unique_ptr<flow::LayerTree> layer_tree) {
}));
}
void RuntimeHolder::DidCreateMainIsolate(Dart_Isolate isolate) {
blink::MojoServices::Create(isolate, nullptr, nullptr,
std::move(root_bundle_));
}
void RuntimeHolder::InitRootBundle(std::vector<char> bundle) {
root_bundle_data_ = std::move(bundle);
asset_store_ = ftl::MakeRefCounted<blink::ZipAssetStore>(
GetUnzipperProviderForRootBundle(), blink::Threads::IO());
new blink::ZipAssetBundle(mojo::GetProxy(&root_bundle_), asset_store_);
}
blink::UnzipperProvider RuntimeHolder::GetUnzipperProviderForRootBundle() {
return [self = GetWeakPtr()]() {
if (!self)
return zip::UniqueUnzipper();
// TODO(abarth): The lifetimes aren't quite right here. The unzipper we
// create here might be passed off to an UnzipJob that runs on a background
// thread. The UnzipJob might outlive this object and be referencing a dead
// root_bundle_data_.
return zip::CreateUnzipper(&self->root_bundle_data_);
};
}
void RuntimeHolder::DidCreateFramebuffer(
mojo::InterfaceHandle<mojo::Framebuffer> framebuffer,
mojo::FramebufferInfoPtr info) {
......
......@@ -5,6 +5,8 @@
#ifndef FLUTTER_CONTENT_HANDLER_RUNTIME_HOLDER_H_
#define FLUTTER_CONTENT_HANDLER_RUNTIME_HOLDER_H_
#include "flutter/assets/unzipper_provider.h"
#include "flutter/assets/zip_asset_store.h"
#include "flutter/flow/layers/layer_tree.h"
#include "flutter/runtime/runtime_controller.h"
#include "flutter/runtime/runtime_delegate.h"
......@@ -13,6 +15,7 @@
#include "lib/ftl/macros.h"
#include "lib/ftl/memory/weak_ptr.h"
#include "mojo/public/interfaces/application/application_connector.mojom.h"
#include "mojo/services/asset_bundle/interfaces/asset_bundle.mojom.h"
#include "mojo/services/framebuffer/interfaces/framebuffer.mojom.h"
namespace flutter_content_handler {
......@@ -24,15 +27,19 @@ class RuntimeHolder : public blink::RuntimeDelegate {
~RuntimeHolder();
void Init(mojo::ApplicationConnectorPtr connector);
void Run(const std::string& script_uri, std::vector<char> snapshot);
void Run(const std::string& script_uri, std::vector<char> bundle);
private:
// |blink::RuntimeDelegate| implementation:
void ScheduleFrame() override;
void Render(std::unique_ptr<flow::LayerTree> layer_tree) override;
void DidCreateMainIsolate(Dart_Isolate isolate) override;
ftl::WeakPtr<RuntimeHolder> GetWeakPtr();
void InitRootBundle(std::vector<char> bundle);
blink::UnzipperProvider GetUnzipperProviderForRootBundle();
void DidCreateFramebuffer(
mojo::InterfaceHandle<mojo::Framebuffer> framebuffer,
mojo::FramebufferInfoPtr info);
......@@ -41,6 +48,10 @@ class RuntimeHolder : public blink::RuntimeDelegate {
void BeginFrame();
void OnFrameComplete();
std::vector<char> root_bundle_data_;
ftl::RefPtr<blink::ZipAssetStore> asset_store_;
mojo::asset_bundle::AssetBundlePtr root_bundle_;
mojo::FramebufferProviderPtr framebuffer_provider_;
std::unique_ptr<Rasterizer> rasterizer_;
std::unique_ptr<blink::RuntimeController> runtime_;
......
......@@ -81,18 +81,19 @@ void MojoServices::Create(Dart_Isolate isolate,
mojo::ServiceProviderPtr incoming_services,
mojo::asset_bundle::AssetBundlePtr root_bundle) {
UIDartState* state = static_cast<UIDartState*>(DartState::From(isolate));
state->set_mojo_services(std::unique_ptr<MojoServices>(new MojoServices(
services.Pass(), incoming_services.Pass(), root_bundle.Pass())));
state->set_mojo_services(std::unique_ptr<MojoServices>(
new MojoServices(std::move(services), std::move(incoming_services),
std::move(root_bundle))));
}
MojoServices::MojoServices(sky::ServicesDataPtr services,
mojo::ServiceProviderPtr incoming_services,
mojo::asset_bundle::AssetBundlePtr root_bundle)
: services_(services.Pass()),
root_bundle_(root_bundle.Pass()),
incoming_services_(incoming_services.Pass()) {
: services_(std::move(services)),
root_bundle_(std::move(root_bundle)),
incoming_services_(std::move(incoming_services)) {
if (services_ && services_->outgoing_services.is_pending()) {
outgoing_services_ = services_->outgoing_services.Pass();
outgoing_services_ = std::move(services_->outgoing_services);
} else {
outgoing_services_ = GetProxy(&services_from_dart_);
}
......
......@@ -293,9 +293,9 @@ void Engine::DidCreateMainIsolate(Dart_Isolate isolate) {
service_provider_bindings_.AddBinding(
&service_provider_impl_, mojo::GetProxy(&services_from_embedder));
blink::MojoServices::Create(isolate, services_.Pass(),
services_from_embedder.Pass(),
root_bundle_.Pass());
blink::MojoServices::Create(isolate, std::move(services_),
std::move(services_from_embedder),
std::move(root_bundle_));
if (asset_store_)
FlutterFontSelector::Install(asset_store_);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册