Skip to content

Commit

Permalink
Remove //base dependency from asset system (flutter#2885)
Browse files Browse the repository at this point in the history
This patch centralizes the asset bundle processing in //flutter/assets and
removes the //base dependency from the code.
  • Loading branch information
abarth authored Aug 8, 2016
1 parent cb40b67 commit 13af58b
Show file tree
Hide file tree
Showing 30 changed files with 792 additions and 541 deletions.
20 changes: 16 additions & 4 deletions services/asset_bundle/BUILD.gn → flutter/assets/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,30 @@

import("//mojo/public/mojo_application.gni")

source_set("lib") {
source_set("assets") {
sources = [
"directory_asset_bundle.cc",
"directory_asset_bundle.h",
"unique_unzipper.cc",
"unique_unzipper.h",
"unzip_job.cc",
"unzip_job.h",
"zip_asset_bundle.cc",
"zip_asset_bundle.h",
"zip_asset_store.cc",
"zip_asset_store.h",
]

deps = [
"//base",
"//mojo/data_pipe_utils",
"//glue",
"//lib/ftl",
"//mojo/public/cpp/bindings:callback",
"//mojo/public/cpp/system",
"//mojo/public/cpp/bindings:utility",
"//third_party/zlib:minizip",
]

public_deps = [
"//mojo/services/asset_bundle/interfaces",
"//third_party/zlib:zip",
]
}
51 changes: 51 additions & 0 deletions flutter/assets/directory_asset_bundle.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// 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/directory_asset_bundle.h"

#include <fcntl.h>
#include <unistd.h>

#include <utility>

#include "glue/data_pipe_utils.h"
#include "lib/ftl/files/eintr_wrapper.h"
#include "lib/ftl/files/path.h"
#include "lib/ftl/files/unique_fd.h"

namespace blink {

void DirectoryAssetBundle::GetAsStream(
const mojo::String& asset_name,
const mojo::Callback<void(mojo::ScopedDataPipeConsumerHandle)>& callback) {
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.";
return;
}

// TODO(abarth): Consider moving the |open| call to task_runner_.
ftl::UniqueFD fd(HANDLE_EINTR(open(asset_path.c_str(), O_RDONLY)));
if (fd.get() < 0)
return;
glue::CopyFromFileDescriptor(std::move(fd), std::move(pipe.producer_handle),
task_runner_.get(), [](bool ignored) {});
}

DirectoryAssetBundle::~DirectoryAssetBundle() {}

DirectoryAssetBundle::DirectoryAssetBundle(
mojo::InterfaceRequest<AssetBundle> request,
std::string directory,
ftl::RefPtr<ftl::TaskRunner> task_runner)
: binding_(this, std::move(request)),
directory_(std::move(directory)),
task_runner_(std::move(task_runner)) {}

} // namespace blink
42 changes: 42 additions & 0 deletions flutter/assets/directory_asset_bundle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// 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_DIRECTORY_ASSET_BUNDLE_H_
#define FLUTTER_ASSETS_DIRECTORY_ASSET_BUNDLE_H_

#include "lib/ftl/macros.h"
#include "lib/ftl/tasks/task_runner.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"

namespace blink {

// A mojo service that serves assets out of a directory.
class DirectoryAssetBundle : public mojo::asset_bundle::AssetBundle {
public:
DirectoryAssetBundle(mojo::InterfaceRequest<AssetBundle> request,
std::string directory,
ftl::RefPtr<ftl::TaskRunner> task_runner);

// mojo::assert_bundle::AssetBundle implementation:
void GetAsStream(
const mojo::String& asset_name,
const mojo::Callback<void(mojo::ScopedDataPipeConsumerHandle)>& callback)
override;

private:
~DirectoryAssetBundle() override;

mojo::StrongBinding<mojo::asset_bundle::AssetBundle> binding_;
const std::string directory_;
ftl::RefPtr<ftl::TaskRunner> task_runner_;

FTL_DISALLOW_COPY_AND_ASSIGN(DirectoryAssetBundle);
};

} // namespace blink

#endif // FLUTTER_ASSETS_DIRECTORY_ASSET_BUNDLE_H_
15 changes: 15 additions & 0 deletions flutter/assets/unique_unzipper.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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/unique_unzipper.h"

#include "third_party/zlib/contrib/minizip/unzip.h"

namespace blink {

void UniqueUnzipperTraits::Free(void* file) {
unzClose(file);
}

} // namespace blink
22 changes: 22 additions & 0 deletions flutter/assets/unique_unzipper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// 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_UNIQUE_UNZIPPER_H_
#define FLUTTER_ASSETS_UNIQUE_UNZIPPER_H_

#include "lib/ftl/memory/unique_object.h"

namespace blink {

struct UniqueUnzipperTraits {
static inline void* InvalidValue() { return nullptr; }
static inline bool IsValid(void* value) { return value != InvalidValue(); }
static void Free(void* file);
};

using UniqueUnzipper = ftl::UniqueObject<void*, UniqueUnzipperTraits>;

} // namespace blink

#endif // FLUTTER_ASSETS_UNIQUE_UNZIPPER_H_
97 changes: 97 additions & 0 deletions flutter/assets/unzip_job.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// 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/unzip_job.h"

#include <utility>

#include "mojo/public/cpp/environment/environment.h"
#include "third_party/zlib/contrib/minizip/unzip.h"

namespace blink {

UnzipJob::UnzipJob(std::string zip_path,
std::string asset_name,
mojo::ScopedDataPipeProducerHandle producer,
ftl::RefPtr<ftl::TaskRunner> task_runner)
: zip_path_(std::move(zip_path)),
asset_name_(std::move(asset_name)),
producer_(std::move(producer)),
task_runner_(std::move(task_runner)),
waiter_(mojo::Environment::GetDefaultAsyncWaiter()),
wait_id_(0) {
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);
if (result != UNZ_OK) {
FTL_LOG(WARNING) << "Requested asset '" << asset_name_
<< "' does not exist.";
delete this;
return;
}

result = unzOpenCurrentFile(zip_file_.get());
if (result != UNZ_OK) {
FTL_LOG(WARNING) << "unzOpenCurrentFile failed, error=" << result;
delete this;
return;
}

OnHandleReady(MOJO_RESULT_OK);
}

void UnzipJob::OnHandleReady(MojoResult result) {
if (result == MOJO_RESULT_OK) {
void* buffer = nullptr;
uint32_t size = 0;
result = mojo::BeginWriteDataRaw(producer_.get(), &buffer, &size,
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);
result = mojo::EndWriteDataRaw(producer_.get(),
std::max<ssize_t>(0l, bytes_read));
if (bytes_read < 0) {
FTL_LOG(WARNING) << "Asset unzip failed, error=" << bytes_read;
delete this;
} else if (result != MOJO_RESULT_OK) {
FTL_LOG(WARNING) << "Mojo EndWrite failed, error=" << result;
delete this;
} else if (bytes_read < size) {
// Reached EOF. Stop the process.
delete this;
} else {
task_runner_->PostTask([this]() { OnHandleReady(MOJO_RESULT_OK); });
}
return;
}
}
if (result == MOJO_RESULT_SHOULD_WAIT) {
wait_id_ =
waiter_->AsyncWait(producer_.get().value(), MOJO_HANDLE_SIGNAL_WRITABLE,
MOJO_DEADLINE_INDEFINITE, &WaitComplete, this);
return;
}
delete this;
}

void UnzipJob::WaitComplete(void* context, MojoResult result) {
UnzipJob* job = static_cast<UnzipJob*>(context);
job->wait_id_ = 0;
job->OnHandleReady(result);
}

} // namespace blink
47 changes: 47 additions & 0 deletions flutter/assets/unzip_job.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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_JOB_H_
#define FLUTTER_ASSETS_UNZIP_JOB_H_

#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 "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,
std::string asset_name,
mojo::ScopedDataPipeProducerHandle producer,
ftl::RefPtr<ftl::TaskRunner> task_runner);
~UnzipJob();

private:
void Start();
void OnHandleReady(MojoResult result);
static void WaitComplete(void* context, MojoResult result);

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

const MojoAsyncWaiter* waiter_;
MojoAsyncWaitID wait_id_;

FTL_DISALLOW_COPY_AND_ASSIGN(UnzipJob);
};

} // namespace blink

#endif // FLUTTER_ASSETS_UNZIP_JOB_H_
26 changes: 26 additions & 0 deletions flutter/assets/zip_asset_bundle.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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/zip_asset_bundle.h"

#include <utility>

namespace blink {

void ZipAssetBundle::GetAsStream(
const mojo::String& asset_name,
const mojo::Callback<void(mojo::ScopedDataPipeConsumerHandle)>& callback) {
mojo::DataPipe pipe;
callback.Run(std::move(pipe.consumer_handle));
store_->GetAsStream(asset_name.get(), std::move(pipe.producer_handle));
}

ZipAssetBundle::ZipAssetBundle(
mojo::InterfaceRequest<mojo::asset_bundle::AssetBundle> request,
ftl::RefPtr<ZipAssetStore> store)
: binding_(this, std::move(request)), store_(std::move(store)) {}

ZipAssetBundle::~ZipAssetBundle() {}

} // namespace blink
36 changes: 36 additions & 0 deletions flutter/assets/zip_asset_bundle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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_ZIP_ASSET_BUNDLE_H_
#define FLUTTER_ASSETS_ZIP_ASSET_BUNDLE_H_

#include "flutter/assets/zip_asset_store.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 {

class ZipAssetBundle : public mojo::asset_bundle::AssetBundle {
public:
ZipAssetBundle(
mojo::InterfaceRequest<mojo::asset_bundle::AssetBundle> request,
ftl::RefPtr<ZipAssetStore> store);

// mojo::assert_bundle::AssetBundle implementation:
void GetAsStream(
const mojo::String& asset_name,
const mojo::Callback<void(mojo::ScopedDataPipeConsumerHandle)>& callback)
override;

private:
~ZipAssetBundle() override;

mojo::StrongBinding<mojo::asset_bundle::AssetBundle> binding_;
ftl::RefPtr<ZipAssetStore> store_;
};

} // namespace blink

#endif // FLUTTER_ASSETS_ZIP_ASSET_BUNDLE_H_
Loading

0 comments on commit 13af58b

Please sign in to comment.