Skip to content

Commit

Permalink
Introduce UnzipperProvider (flutter#3004)
Browse files Browse the repository at this point in the history
This patch abstracts where the content of the zip file is stored.
Currently, zip files are stored in the file system, but in Fuchsia,
we're going to store them in memory (at least for the time being).
Rather than represent a zip file as a path in the file system, we
instead use an UnzipperProvider, which can create zip::UniqueUnzipper
objects on demand.
  • Loading branch information
abarth authored Sep 7, 2016
1 parent 81574be commit ca17c1c
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 74 deletions.
5 changes: 3 additions & 2 deletions assets/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ source_set("assets") {
sources = [
"directory_asset_bundle.cc",
"directory_asset_bundle.h",
"unique_unzipper.cc",
"unique_unzipper.h",
"unzip_job.cc",
"unzip_job.h",
"unzipper_provider.cc",
"unzipper_provider.h",
"zip_asset_bundle.cc",
"zip_asset_bundle.h",
"zip_asset_store.cc",
Expand All @@ -19,6 +19,7 @@ source_set("assets") {
deps = [
"//flutter/glue",
"//lib/ftl",
"//lib/zip",
"//mojo/public/cpp/bindings:callback",
"//mojo/public/cpp/system",
"//mojo/public/cpp/bindings:utility",
Expand Down
15 changes: 0 additions & 15 deletions assets/unique_unzipper.cc

This file was deleted.

22 changes: 0 additions & 22 deletions assets/unique_unzipper.h

This file was deleted.

19 changes: 6 additions & 13 deletions assets/unzip_job.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,32 @@

namespace blink {

UnzipJob::UnzipJob(std::string zip_path,
UnzipJob::UnzipJob(zip::UniqueUnzipper unzipper,
std::string asset_name,
mojo::ScopedDataPipeProducerHandle producer,
ftl::RefPtr<ftl::TaskRunner> task_runner)
: zip_path_(std::move(zip_path)),
: unzipper_(std::move(unzipper)),
asset_name_(std::move(asset_name)),
producer_(std::move(producer)),
task_runner_(std::move(task_runner)),
waiter_(mojo::Environment::GetDefaultAsyncWaiter()),
wait_id_(0) {
FTL_DCHECK(unzipper_.is_valid());
task_runner_->PostTask([this]() { Start(); });
}

UnzipJob::~UnzipJob() {}

void UnzipJob::Start() {
zip_file_.reset(unzOpen2(zip_path_.c_str(), nullptr));

if (!zip_file_.is_valid()) {
FTL_LOG(ERROR) << "Unable to open ZIP file: " << zip_path_;
delete this;
return;
}

int result = unzLocateFile(zip_file_.get(), asset_name_.c_str(), 0);
int result = unzLocateFile(unzipper_.get(), asset_name_.c_str(), 0);
if (result != UNZ_OK) {
FTL_LOG(WARNING) << "Requested asset '" << asset_name_
<< "' does not exist.";
delete this;
return;
}

result = unzOpenCurrentFile(zip_file_.get());
result = unzOpenCurrentFile(unzipper_.get());
if (result != UNZ_OK) {
FTL_LOG(WARNING) << "unzOpenCurrentFile failed, error=" << result;
delete this;
Expand All @@ -61,7 +54,7 @@ void UnzipJob::OnHandleReady(MojoResult result) {
MOJO_WRITE_DATA_FLAG_NONE);
if (result == MOJO_RESULT_OK) {
FTL_DCHECK(size < static_cast<uint32_t>(std::numeric_limits<int>::max()));
ssize_t bytes_read = unzReadCurrentFile(zip_file_.get(), buffer, size);
ssize_t bytes_read = unzReadCurrentFile(unzipper_.get(), buffer, size);
result = mojo::EndWriteDataRaw(producer_.get(),
std::max<ssize_t>(0l, bytes_read));
if (bytes_read < 0) {
Expand Down
7 changes: 3 additions & 4 deletions assets/unzip_job.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@
#include <map>
#include <vector>

#include "flutter/assets/unique_unzipper.h"
#include "lib/ftl/macros.h"
#include "lib/ftl/memory/ref_counted.h"
#include "lib/ftl/tasks/task_runner.h"
#include "lib/zip/unique_unzipper.h"
#include "mojo/public/cpp/environment/async_waiter.h"
#include "mojo/services/asset_bundle/interfaces/asset_bundle.mojom.h"

namespace blink {

class UnzipJob {
public:
UnzipJob(std::string zip_path,
UnzipJob(zip::UniqueUnzipper unzipper,
std::string asset_name,
mojo::ScopedDataPipeProducerHandle producer,
ftl::RefPtr<ftl::TaskRunner> task_runner);
Expand All @@ -30,11 +30,10 @@ class UnzipJob {
void OnHandleReady(MojoResult result);
static void WaitComplete(void* context, MojoResult result);

const std::string zip_path_;
zip::UniqueUnzipper unzipper_;
const std::string asset_name_;
mojo::ScopedDataPipeProducerHandle producer_;
ftl::RefPtr<ftl::TaskRunner> task_runner_;
UniqueUnzipper zip_file_;

const MojoAsyncWaiter* waiter_;
MojoAsyncWaitID wait_id_;
Expand Down
21 changes: 21 additions & 0 deletions assets/unzipper_provider.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/assets/unzipper_provider.h"

#include "lib/ftl/logging.h"
#include "third_party/zlib/contrib/minizip/unzip.h"

namespace blink {

UnzipperProvider GetUnzipperProviderForPath(std::string zip_path) {
return [zip_path]() {
zip::UniqueUnzipper unzipper(unzOpen2(zip_path.c_str(), nullptr));
if (!unzipper.is_valid())
FTL_LOG(ERROR) << "Unable to open zip file: " << zip_path;
return unzipper;
};
}

} // namespace blink
20 changes: 20 additions & 0 deletions assets/unzipper_provider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_ASSETS_UNZIP_PROVIDER_H_
#define FLUTTER_ASSETS_UNZIP_PROVIDER_H_

#include <functional>

#include "lib/zip/unique_unzipper.h"

namespace blink {

using UnzipperProvider = std::function<zip::UniqueUnzipper()>;

UnzipperProvider GetUnzipperProviderForPath(std::string zip_path);

} // namespace blink

#endif // FLUTTER_ASSETS_UNZIP_PROVIDER_H_
27 changes: 15 additions & 12 deletions assets/zip_asset_store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@

#include <utility>

#include "flutter/assets/unique_unzipper.h"
#include "flutter/assets/unzip_job.h"
#include "flutter/glue/data_pipe_utils.h"
#include "lib/ftl/files/eintr_wrapper.h"
#include "lib/ftl/files/unique_fd.h"
#include "lib/zip/unique_unzipper.h"
#include "third_party/zlib/contrib/minizip/unzip.h"

namespace blink {

ZipAssetStore::ZipAssetStore(std::string zip_path,
ZipAssetStore::ZipAssetStore(UnzipperProvider unzipper_provider,
ftl::RefPtr<ftl::TaskRunner> task_runner)
: zip_path_(std::move(zip_path)), task_runner_(std::move(task_runner)) {}
: unzipper_provider_(std::move(unzipper_provider)),
task_runner_(std::move(task_runner)) {}

ZipAssetStore::~ZipAssetStore() {}

Expand All @@ -40,32 +41,34 @@ void ZipAssetStore::GetAsStream(const std::string& asset_name,
glue::CopyFromFileDescriptor(std::move(fd), std::move(producer),
task_runner_.get(), [](bool ignored) {});
} else {
new UnzipJob(zip_path_, asset_name, std::move(producer), task_runner_);
zip::UniqueUnzipper unzipper = unzipper_provider_();
if (!unzipper.is_valid())
return;
new UnzipJob(std::move(unzipper), asset_name, std::move(producer),
task_runner_);
}
}

bool ZipAssetStore::GetAsBuffer(const std::string& asset_name,
std::vector<uint8_t>* data) {
UniqueUnzipper zip_file(unzOpen2(zip_path_.c_str(), nullptr));
if (!zip_file.is_valid()) {
FTL_LOG(ERROR) << "Unable to open ZIP file: " << zip_path_;
zip::UniqueUnzipper unzipper = unzipper_provider_();
if (!unzipper.is_valid())
return false;
}

int result = unzLocateFile(zip_file.get(), asset_name.c_str(), 0);
int result = unzLocateFile(unzipper.get(), asset_name.c_str(), 0);
if (result != UNZ_OK) {
return false;
}

unz_file_info file_info;
result = unzGetCurrentFileInfo(zip_file.get(), &file_info, nullptr, 0,
result = unzGetCurrentFileInfo(unzipper.get(), &file_info, nullptr, 0,
nullptr, 0, nullptr, 0);
if (result != UNZ_OK) {
FTL_LOG(WARNING) << "unzGetCurrentFileInfo failed, error=" << result;
return false;
}

result = unzOpenCurrentFile(zip_file.get());
result = unzOpenCurrentFile(unzipper.get());
if (result != UNZ_OK) {
FTL_LOG(WARNING) << "unzOpenCurrentFile failed, error=" << result;
return false;
Expand All @@ -75,7 +78,7 @@ bool ZipAssetStore::GetAsBuffer(const std::string& asset_name,
int total_read = 0;
while (total_read < static_cast<int>(data->size())) {
int bytes_read = unzReadCurrentFile(
zip_file.get(), data->data() + total_read, data->size() - total_read);
unzipper.get(), data->data() + total_read, data->size() - total_read);
if (bytes_read <= 0)
return false;
total_read += bytes_read;
Expand Down
6 changes: 4 additions & 2 deletions assets/zip_asset_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <map>
#include <vector>

#include "flutter/assets/unzipper_provider.h"
#include "lib/ftl/macros.h"
#include "lib/ftl/memory/ref_counted.h"
#include "lib/ftl/tasks/task_runner.h"
Expand All @@ -17,7 +18,8 @@ namespace blink {

class ZipAssetStore : public ftl::RefCountedThreadSafe<ZipAssetStore> {
public:
ZipAssetStore(std::string zip_path, ftl::RefPtr<ftl::TaskRunner> task_runner);
ZipAssetStore(UnzipperProvider unzipper_provider,
ftl::RefPtr<ftl::TaskRunner> task_runner);
~ZipAssetStore();

// Serve this asset from another file instead of using the ZIP contents.
Expand All @@ -28,7 +30,7 @@ class ZipAssetStore : public ftl::RefCountedThreadSafe<ZipAssetStore> {
bool GetAsBuffer(const std::string& asset_name, std::vector<uint8_t>* data);

private:
const std::string zip_path_;
UnzipperProvider unzipper_provider_;
ftl::RefPtr<ftl::TaskRunner> task_runner_;
std::map<std::string, std::string> overlay_files_;

Expand Down
6 changes: 4 additions & 2 deletions runtime/dart_init.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "dart/runtime/bin/embedded_dart_io.h"
#include "dart/runtime/include/dart_mirrors_api.h"
#include "flutter/assets/unzipper_provider.h"
#include "flutter/assets/zip_asset_store.h"
#include "flutter/common/settings.h"
#include "flutter/glue/trace_event.h"
Expand Down Expand Up @@ -247,8 +248,9 @@ Dart_Isolate IsolateCreateCallback(const char* script_uri,
FTL_CHECK(uri.find(kFileUriPrefix) == 0u);
std::string bundle_path(script_uri + strlen(kFileUriPrefix));
ftl::RefPtr<ZipAssetStore> zip_asset_store =
ftl::MakeRefCounted<ZipAssetStore>(std::move(bundle_path),
ftl::RefPtr<ftl::TaskRunner>());
ftl::MakeRefCounted<ZipAssetStore>(
GetUnzipperProviderForPath(std::move(bundle_path)),
ftl::RefPtr<ftl::TaskRunner>());
FTL_CHECK(zip_asset_store->GetAsBuffer(kSnapshotAssetKey, &snapshot_data));
}

Expand Down
5 changes: 3 additions & 2 deletions sky/shell/ui/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <utility>

#include "flutter/assets/directory_asset_bundle.h"
#include "flutter/assets/unzipper_provider.h"
#include "flutter/assets/zip_asset_bundle.h"
#include "flutter/common/threads.h"
#include "flutter/glue/movable_wrapper.h"
Expand Down Expand Up @@ -204,8 +205,8 @@ void Engine::ConfigureAssetBundle(const std::string& path) {

if (S_ISREG(stat_result.st_mode)) {
// Zip asset bundle.
asset_store_ =
ftl::MakeRefCounted<blink::ZipAssetStore>(path, blink::Threads::IO());
asset_store_ = ftl::MakeRefCounted<blink::ZipAssetStore>(
blink::GetUnzipperProviderForPath(path), blink::Threads::IO());
new blink::ZipAssetBundle(mojo::GetProxy(&root_bundle_), asset_store_);
return;
}
Expand Down

0 comments on commit ca17c1c

Please sign in to comment.