Servicify unzipping and use it in the component updater.
Bug: 792066
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: I910f5dde8cb7c071c4aeb6e3a0db04b301db1063
Reviewed-on: https://chromium-review.googlesource.com/809264
Reviewed-by: Colin Blundell <[email protected]>
Reviewed-by: Tom Sepez <[email protected]>
Reviewed-by: Ilya Sherman <[email protected]>
Reviewed-by: Nico Weber <[email protected]>
Reviewed-by: Rohit Rao <[email protected]>
Reviewed-by: Jay Civelli <[email protected]>
Reviewed-by: Cait Phillips <[email protected]>
Reviewed-by: Sorin Jianu <[email protected]>
Reviewed-by: Ken Rockot <[email protected]>
Commit-Queue: Joshua Pawlicki <[email protected]>
Cr-Commit-Position: refs/heads/master@{#538109}
diff --git a/components/component_updater/component_installer_unittest.cc b/components/component_updater/component_installer_unittest.cc
index 476ed96a..a1f6717 100644
--- a/components/component_updater/component_installer_unittest.cc
+++ b/components/component_updater/component_installer_unittest.cc
@@ -217,9 +217,10 @@
}
void ComponentInstallerTest::Unpack(const base::FilePath& crx_path) {
+ auto config = base::MakeRefCounted<TestConfigurator>();
auto component_unpacker = base::MakeRefCounted<ComponentUnpacker>(
std::vector<uint8_t>(std::begin(kSha256Hash), std::end(kSha256Hash)),
- crx_path, nullptr, nullptr);
+ crx_path, nullptr, config->CreateServiceManagerConnector());
component_unpacker->Unpack(base::BindOnce(
&ComponentInstallerTest::UnpackComplete, base::Unretained(this)));
RunThreads();
diff --git a/components/filesystem/public/interfaces/types.mojom b/components/filesystem/public/interfaces/types.mojom
index c3abf6c..7c8fff8 100644
--- a/components/filesystem/public/interfaces/types.mojom
+++ b/components/filesystem/public/interfaces/types.mojom
@@ -79,6 +79,8 @@
const uint32 kFlagAppend = 0x80;
// Deletes the file when closed.
const uint32 kDeleteOnClose = 0x2000;
+// May change modified time of the file (used on Windows only).
+const uint32 kFlagWriteAttributes = 0x4000;
// File types.
//
diff --git a/components/unzip_service/BUILD.gn b/components/unzip_service/BUILD.gn
new file mode 100644
index 0000000..ea7e53f
--- /dev/null
+++ b/components/unzip_service/BUILD.gn
@@ -0,0 +1,32 @@
+# Copyright 2017 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.
+
+import("//services/service_manager/public/cpp/service.gni")
+import("//services/service_manager/public/service_manifest.gni")
+
+source_set("lib") {
+ sources = [
+ "unzip_service.cc",
+ "unzip_service.h",
+ "unzipper_impl.cc",
+ "unzipper_impl.h",
+ ]
+
+ deps = [
+ "//base",
+ "//mojo/public/cpp/bindings",
+ "//third_party/zlib/google:zip",
+ ]
+
+ public_deps = [
+ "//components/filesystem/public/interfaces",
+ "//components/unzip_service/public/interfaces",
+ "//services/service_manager/public/cpp",
+ ]
+}
+
+service_manifest("manifest") {
+ name = "unzip_service"
+ source = "manifest.json"
+}
diff --git a/components/unzip_service/DEPS b/components/unzip_service/DEPS
new file mode 100644
index 0000000..116747a
--- /dev/null
+++ b/components/unzip_service/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+ "+components/filesystem",
+ "+mojo/public",
+ "+services/service_manager/public",
+ "+third_party/zlib/google",
+]
diff --git a/components/unzip_service/OWNERS b/components/unzip_service/OWNERS
new file mode 100644
index 0000000..bd74fe69
--- /dev/null
+++ b/components/unzip_service/OWNERS
@@ -0,0 +1,4 @@
[email protected]
[email protected]
+per-file manifest.json=set noparent
+per-file manifest.json=file://ipc/SECURITY_OWNERS
diff --git a/components/unzip_service/manifest.json b/components/unzip_service/manifest.json
new file mode 100644
index 0000000..b21cb37
--- /dev/null
+++ b/components/unzip_service/manifest.json
@@ -0,0 +1,15 @@
+{
+ "name": "unzip_service",
+ "display_name": "Unzip Service",
+ "sandbox_type": "utility",
+ "interface_provider_specs": {
+ "service_manager:connector": {
+ "provides": {
+ "unzip_file": [ "unzip::mojom::Unzipper" ]
+ },
+ "requires": {
+ "service_manager": [ "service_manager:all_users" ]
+ }
+ }
+ }
+}
diff --git a/components/unzip_service/public/cpp/BUILD.gn b/components/unzip_service/public/cpp/BUILD.gn
new file mode 100644
index 0000000..83bc8ae
--- /dev/null
+++ b/components/unzip_service/public/cpp/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2017 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+source_set("cpp") {
+ sources = [
+ "unzip.cc",
+ "unzip.h",
+ ]
+
+ public_deps = [
+ "//components/filesystem:lib",
+ "//components/unzip_service/public/interfaces",
+ "//services/service_manager/public/cpp",
+ ]
+}
diff --git a/components/unzip_service/public/cpp/unzip.cc b/components/unzip_service/public/cpp/unzip.cc
new file mode 100644
index 0000000..f30e8c6
--- /dev/null
+++ b/components/unzip_service/public/cpp/unzip.cc
@@ -0,0 +1,94 @@
+// Copyright 2017 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 "components/unzip_service/public/cpp/unzip.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/string16.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/filesystem/directory_impl.h"
+#include "components/filesystem/lock_table.h"
+#include "components/unzip_service/public/interfaces/constants.mojom.h"
+#include "components/unzip_service/public/interfaces/unzipper.mojom.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace unzip {
+
+namespace {
+
+class UnzipParams : public base::RefCounted<UnzipParams> {
+ public:
+ UnzipParams(mojom::UnzipperPtr unzipper, UnzipCallback callback)
+ : unzipper_(std::move(unzipper)), callback_(std::move(callback)) {}
+
+ mojom::UnzipperPtr* unzipper() { return &unzipper_; }
+
+ UnzipCallback TakeCallback() { return std::move(callback_); }
+
+ private:
+ friend class base::RefCounted<UnzipParams>;
+
+ ~UnzipParams() = default;
+
+ // The UnzipperPtr is stored so it does not get deleted before the callback
+ // runs.
+ mojom::UnzipperPtr unzipper_;
+
+ UnzipCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(UnzipParams);
+};
+
+void UnzipDone(scoped_refptr<UnzipParams> params, bool success) {
+ UnzipCallback cb = params->TakeCallback();
+ if (!cb.is_null())
+ std::move(cb).Run(success);
+}
+
+} // namespace
+
+void Unzip(service_manager::Connector* connector,
+ const base::FilePath& zip_path,
+ const base::FilePath& output_dir,
+ UnzipCallback callback) {
+ DCHECK(!callback.is_null());
+
+ base::File zip_file(zip_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+
+ if (!zip_file.IsValid()) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), false));
+ return;
+ }
+
+ filesystem::mojom::DirectoryPtr directory_ptr;
+ mojo::MakeStrongBinding(
+ std::make_unique<filesystem::DirectoryImpl>(output_dir, nullptr, nullptr),
+ mojo::MakeRequest(&directory_ptr));
+
+ mojom::UnzipperPtr unzipper;
+ connector->BindInterface(mojom::kServiceName, mojo::MakeRequest(&unzipper));
+
+ // |callback| is shared between the connection error handler and the Unzip
+ // call using a refcounted UnzipParams object that owns |callback|.
+ auto unzip_params = base::MakeRefCounted<UnzipParams>(std::move(unzipper),
+ std::move(callback));
+
+ unzip_params->unzipper()->set_connection_error_handler(
+ base::BindRepeating(&UnzipDone, unzip_params, false));
+ (*unzip_params->unzipper())
+ ->Unzip(std::move(zip_file), std::move(directory_ptr),
+ base::BindOnce(&UnzipDone, unzip_params));
+}
+
+} // namespace unzip
diff --git a/components/unzip_service/public/cpp/unzip.h b/components/unzip_service/public/cpp/unzip.h
new file mode 100644
index 0000000..14b4b1f0
--- /dev/null
+++ b/components/unzip_service/public/cpp/unzip.h
@@ -0,0 +1,30 @@
+// Copyright 2017 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 COMPONENTS_UNZIP_SERVICE_PUBLIC_CPP_UNZIP_H_
+#define COMPONENTS_UNZIP_SERVICE_PUBLIC_CPP_UNZIP_H_
+
+#include "base/callback_forward.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace service_manager {
+class Connector;
+}
+
+namespace unzip {
+
+// Unzips |zip_file| into |output_dir|.
+using UnzipCallback = base::OnceCallback<void(bool result)>;
+// TODO(waffles): Unzip can only be called on blockable threads (never UI).
+void Unzip(service_manager::Connector* connector,
+ const base::FilePath& zip_file,
+ const base::FilePath& output_dir,
+ UnzipCallback result_callback);
+
+} // namespace unzip
+
+#endif // COMPONENTS_UNZIP_SERVICE_PUBLIC_CPP_UNZIP_H_
diff --git a/components/unzip_service/public/interfaces/BUILD.gn b/components/unzip_service/public/interfaces/BUILD.gn
new file mode 100644
index 0000000..d048a589
--- /dev/null
+++ b/components/unzip_service/public/interfaces/BUILD.gn
@@ -0,0 +1,23 @@
+# Copyright 2017 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("interfaces") {
+ sources = [
+ "unzipper.mojom",
+ ]
+
+ public_deps = [
+ ":constants",
+ "//components/filesystem/public/interfaces",
+ "//mojo/common:common_custom_types",
+ ]
+}
+
+mojom("constants") {
+ sources = [
+ "constants.mojom",
+ ]
+}
diff --git a/components/unzip_service/public/interfaces/OWNERS b/components/unzip_service/public/interfaces/OWNERS
new file mode 100644
index 0000000..08850f4
--- /dev/null
+++ b/components/unzip_service/public/interfaces/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/components/unzip_service/public/interfaces/README.md b/components/unzip_service/public/interfaces/README.md
new file mode 100644
index 0000000..2c3d6a0
--- /dev/null
+++ b/components/unzip_service/public/interfaces/README.md
@@ -0,0 +1 @@
+Mojo service that exposes an interface that can be used to unzip ZIP files.
diff --git a/components/unzip_service/public/interfaces/constants.mojom b/components/unzip_service/public/interfaces/constants.mojom
new file mode 100644
index 0000000..6cf09d156
--- /dev/null
+++ b/components/unzip_service/public/interfaces/constants.mojom
@@ -0,0 +1,7 @@
+// Copyright 2017 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.
+
+module unzip.mojom;
+
+const string kServiceName = "unzip_service";
diff --git a/components/unzip_service/public/interfaces/unzipper.mojom b/components/unzip_service/public/interfaces/unzipper.mojom
new file mode 100644
index 0000000..19e2153
--- /dev/null
+++ b/components/unzip_service/public/interfaces/unzipper.mojom
@@ -0,0 +1,15 @@
+// Copyright 2017 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.
+
+module unzip.mojom;
+
+import "mojo/common/file.mojom";
+import "components/filesystem/public/interfaces/directory.mojom";
+
+interface Unzipper {
+ // Unzip |zip_file| into |output_dir|.
+ // Returns true on success, false otherwise.
+ Unzip(mojo.common.mojom.File zip_file, filesystem.mojom.Directory output_dir)
+ => (bool result);
+};
diff --git a/components/unzip_service/unzip_service.cc b/components/unzip_service/unzip_service.cc
new file mode 100644
index 0000000..dc38d52
--- /dev/null
+++ b/components/unzip_service/unzip_service.cc
@@ -0,0 +1,46 @@
+// Copyright 2017 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 "components/unzip_service/unzip_service.h"
+
+#include "build/build_config.h"
+#include "components/unzip_service/unzipper_impl.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace unzip {
+
+namespace {
+
+void OnUnzipRequest(service_manager::ServiceContextRefFactory* ref_factory,
+ unzip::mojom::UnzipperRequest request) {
+ mojo::MakeStrongBinding(
+ std::make_unique<UnzipperImpl>(ref_factory->CreateRef()),
+ std::move(request));
+}
+
+} // namespace
+
+UnzipService::UnzipService() = default;
+
+UnzipService::~UnzipService() = default;
+
+std::unique_ptr<service_manager::Service> UnzipService::CreateService() {
+ return std::make_unique<UnzipService>();
+}
+
+void UnzipService::OnStart() {
+ ref_factory_ = std::make_unique<service_manager::ServiceContextRefFactory>(
+ context()->CreateQuitClosure());
+ registry_.AddInterface(
+ base::BindRepeating(&OnUnzipRequest, ref_factory_.get()));
+}
+
+void UnzipService::OnBindInterface(
+ const service_manager::BindSourceInfo& source_info,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle interface_pipe) {
+ registry_.BindInterface(interface_name, std::move(interface_pipe));
+}
+
+} // namespace unzip
diff --git a/components/unzip_service/unzip_service.h b/components/unzip_service/unzip_service.h
new file mode 100644
index 0000000..bca9f89a
--- /dev/null
+++ b/components/unzip_service/unzip_service.h
@@ -0,0 +1,39 @@
+// Copyright 2017 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 COMPONENTS_UNZIP_SERVICE_UNZIP_SERVICE_H_
+#define COMPONENTS_UNZIP_SERVICE_UNZIP_SERVICE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+#include "services/service_manager/public/cpp/service_context.h"
+#include "services/service_manager/public/cpp/service_context_ref.h"
+
+namespace unzip {
+
+class UnzipService : public service_manager::Service {
+ public:
+ UnzipService();
+ ~UnzipService() override;
+ // Factory method for creating the service.
+ static std::unique_ptr<service_manager::Service> CreateService();
+ // Lifescycle events that occur after the service has started to spinup.
+ void OnStart() override;
+ void OnBindInterface(const service_manager::BindSourceInfo& source_info,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle interface_pipe) override;
+
+ private:
+ // State needed to manage service lifecycle and lifecycle of bound clients.
+ std::unique_ptr<service_manager::ServiceContextRefFactory> ref_factory_;
+ service_manager::BinderRegistry registry_;
+ DISALLOW_COPY_AND_ASSIGN(UnzipService);
+};
+
+} // namespace unzip
+
+#endif // COMPONENTS_UNZIP_SERVICE_UNZIP_SERVICE_H_
diff --git a/components/unzip_service/unzipper_impl.cc b/components/unzip_service/unzipper_impl.cc
new file mode 100644
index 0000000..09001109
--- /dev/null
+++ b/components/unzip_service/unzipper_impl.cc
@@ -0,0 +1,107 @@
+// Copyright 2017 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 "components/unzip_service/unzipper_impl.h"
+
+#include "base/compiler_specific.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "third_party/zlib/google/zip.h"
+#include "third_party/zlib/google/zip_reader.h"
+
+namespace unzip {
+
+namespace {
+
+// A writer delegate that reports errors instead of writing.
+class DudWriterDelegate : public zip::WriterDelegate {
+ public:
+ DudWriterDelegate() {}
+ ~DudWriterDelegate() override {}
+
+ // WriterDelegate methods:
+ bool PrepareOutput() override { return false; }
+ bool WriteBytes(const char* data, int num_bytes) override { return false; }
+ void SetTimeModified(const base::Time& time) override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DudWriterDelegate);
+};
+
+std::string PathToMojoString(const base::FilePath& path) {
+#if defined(OS_WIN)
+ return base::WideToUTF8(path.value());
+#else
+ return path.value();
+#endif
+}
+
+// Modifies output_dir to point to the final directory.
+bool CreateDirectory(filesystem::mojom::DirectoryPtr* output_dir,
+ const base::FilePath& path) {
+ filesystem::mojom::FileError err = filesystem::mojom::FileError::OK;
+ return (*output_dir)
+ ->OpenDirectory(PathToMojoString(path), nullptr,
+ filesystem::mojom::kFlagOpenAlways, &err) &&
+ err == filesystem::mojom::FileError::OK;
+}
+
+std::unique_ptr<zip::WriterDelegate> MakeFileWriterDelegateNoParent(
+ filesystem::mojom::DirectoryPtr* output_dir,
+ const base::FilePath& path) {
+ auto file = std::make_unique<base::File>();
+ filesystem::mojom::FileError err;
+ if (!(*output_dir)
+ ->OpenFileHandle(PathToMojoString(path),
+ filesystem::mojom::kFlagCreate |
+ filesystem::mojom::kFlagWrite |
+ filesystem::mojom::kFlagWriteAttributes,
+ &err, file.get()) ||
+ err != filesystem::mojom::FileError::OK) {
+ return std::make_unique<DudWriterDelegate>();
+ }
+ return std::make_unique<zip::FileWriterDelegate>(std::move(file));
+}
+
+std::unique_ptr<zip::WriterDelegate> MakeFileWriterDelegate(
+ filesystem::mojom::DirectoryPtr* output_dir,
+ const base::FilePath& path) {
+ if (path == path.BaseName())
+ return MakeFileWriterDelegateNoParent(output_dir, path);
+ filesystem::mojom::DirectoryPtr parent;
+ filesystem::mojom::FileError err;
+ if (!(*output_dir)
+ ->OpenDirectory(PathToMojoString(path.DirName()),
+ mojo::MakeRequest(&parent),
+ filesystem::mojom::kFlagOpenAlways, &err) ||
+ err != filesystem::mojom::FileError::OK) {
+ return std::make_unique<DudWriterDelegate>();
+ }
+ return MakeFileWriterDelegateNoParent(&parent, path.BaseName());
+}
+
+bool FilterNoFiles(const base::FilePath& unused) {
+ return true;
+}
+
+} // namespace
+
+UnzipperImpl::UnzipperImpl(
+ std::unique_ptr<service_manager::ServiceContextRef> service_ref)
+ : service_ref_(std::move(service_ref)) {}
+
+UnzipperImpl::~UnzipperImpl() = default;
+
+void UnzipperImpl::Unzip(base::File zip_file,
+ filesystem::mojom::DirectoryPtr output_dir,
+ UnzipCallback callback) {
+ DCHECK(zip_file.IsValid());
+ std::move(callback).Run(zip::UnzipWithFilterAndWriters(
+ zip_file.GetPlatformFile(),
+ base::BindRepeating(&MakeFileWriterDelegate, &output_dir),
+ base::BindRepeating(&CreateDirectory, &output_dir),
+ base::BindRepeating(&FilterNoFiles), false));
+}
+
+} // namespace unzip
diff --git a/components/unzip_service/unzipper_impl.h b/components/unzip_service/unzipper_impl.h
new file mode 100644
index 0000000..6bb6d34
--- /dev/null
+++ b/components/unzip_service/unzipper_impl.h
@@ -0,0 +1,36 @@
+// Copyright 2017 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 COMPONENTS_UNZIP_SERVICE_UNZIPPER_IMPL_H_
+#define COMPONENTS_UNZIP_SERVICE_UNZIPPER_IMPL_H_
+
+#include <memory>
+
+#include "base/files/file.h"
+#include "base/macros.h"
+#include "components/unzip_service/public/interfaces/unzipper.mojom.h"
+#include "services/service_manager/public/cpp/service_context_ref.h"
+
+namespace unzip {
+
+class UnzipperImpl : public mojom::Unzipper {
+ public:
+ explicit UnzipperImpl(
+ std::unique_ptr<service_manager::ServiceContextRef> service_ref);
+ ~UnzipperImpl() override;
+
+ private:
+ // unzip::mojom::Unzipper:
+ void Unzip(base::File zip_file,
+ filesystem::mojom::DirectoryPtr output_dir,
+ UnzipCallback callback) override;
+
+ const std::unique_ptr<service_manager::ServiceContextRef> service_ref_;
+
+ DISALLOW_COPY_AND_ASSIGN(UnzipperImpl);
+};
+
+} // namespace unzip
+
+#endif // COMPONENTS_UNZIP_SERVICE_UNZIPPER_IMPL_H_
diff --git a/components/update_client/BUILD.gn b/components/update_client/BUILD.gn
index 675c7be0..c912252 100644
--- a/components/update_client/BUILD.gn
+++ b/components/update_client/BUILD.gn
@@ -69,12 +69,12 @@
"//components/data_use_measurement/core",
"//components/patch_service/public/cpp",
"//components/prefs",
+ "//components/unzip_service/public/cpp",
"//components/version_info:version_info",
"//courgette:courgette_lib",
"//crypto",
"//net",
"//third_party/libxml",
- "//third_party/zlib/google:zip",
"//url",
]
libs = []
@@ -97,12 +97,16 @@
public_deps = [
":update_client",
]
+
deps = [
"//base",
"//components/patch_service:lib",
"//components/prefs",
+ "//components/unzip_service:lib",
+ "//mojo/public/cpp/bindings",
"//net:test_support",
- "//services/service_manager/public/cpp/test:test_support",
+ "//services/service_manager/public/cpp",
+ "//services/service_manager/public/mojom",
"//testing/gmock",
"//testing/gtest",
"//url",
diff --git a/components/update_client/DEPS b/components/update_client/DEPS
index 30e7de9..64005e1a 100644
--- a/components/update_client/DEPS
+++ b/components/update_client/DEPS
@@ -4,10 +4,12 @@
"+components/data_use_measurement/core",
"+components/patch_service",
"+components/prefs",
+ "+components/unzip_service",
"+components/version_info",
"+courgette",
"+crypto",
"+libxml",
+ "+mojo",
"+net",
"+services/service_manager/public",
"+third_party/libxml",
diff --git a/components/update_client/action_runner.cc b/components/update_client/action_runner.cc
index be8706c4..ded657e 100644
--- a/components/update_client/action_runner.cc
+++ b/components/update_client/action_runner.cc
@@ -19,6 +19,7 @@
#include "components/update_client/configurator.h"
#include "components/update_client/task_traits.h"
#include "components/update_client/update_client.h"
+#include "components/update_client/update_engine.h"
namespace update_client {
@@ -36,11 +37,14 @@
run_complete_ = std::move(run_complete);
base::CreateSequencedTaskRunnerWithTraits(kTaskTraits)
- ->PostTask(FROM_HERE,
- base::BindOnce(&ActionRunner::Unpack, base::Unretained(this)));
+ ->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ActionRunner::Unpack, base::Unretained(this),
+ component_.config()->CreateServiceManagerConnector()));
}
-void ActionRunner::Unpack() {
+void ActionRunner::Unpack(
+ std::unique_ptr<service_manager::Connector> connector) {
const auto& installer = component_.crx_component().installer;
base::FilePath file_path;
@@ -48,8 +52,8 @@
// Contains the key hash of the CRX this object is allowed to run.
const auto key_hash = component_.config()->GetRunActionKeyHash();
- auto unpacker = base::MakeRefCounted<ComponentUnpacker>(key_hash, file_path,
- installer, nullptr);
+ auto unpacker = base::MakeRefCounted<ComponentUnpacker>(
+ key_hash, file_path, installer, std::move(connector));
unpacker->Unpack(
base::BindOnce(&ActionRunner::UnpackComplete, base::Unretained(this)));
}
diff --git a/components/update_client/action_runner.h b/components/update_client/action_runner.h
index 877d9c2..b63571c 100644
--- a/components/update_client/action_runner.h
+++ b/components/update_client/action_runner.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <memory>
#include <utility>
#include <vector>
@@ -38,7 +39,7 @@
void Run(Callback run_complete);
private:
- void Unpack();
+ void Unpack(std::unique_ptr<service_manager::Connector> connector);
void UnpackComplete(const ComponentUnpacker::Result& result);
void RunCommand(const base::CommandLine& cmdline);
diff --git a/components/update_client/component_unpacker.cc b/components/update_client/component_unpacker.cc
index eae811e..9e27a11 100644
--- a/components/update_client/component_unpacker.cc
+++ b/components/update_client/component_unpacker.cc
@@ -21,10 +21,10 @@
#include "base/strings/stringprintf.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/crx_file/crx_verifier.h"
+#include "components/unzip_service/public/cpp/unzip.h"
#include "components/update_client/component_patcher.h"
#include "components/update_client/update_client.h"
#include "components/update_client/update_client_errors.h"
-#include "third_party/zlib/google/zip.h"
namespace update_client {
@@ -45,13 +45,9 @@
ComponentUnpacker::~ComponentUnpacker() {}
-bool ComponentUnpacker::UnpackInternal() {
- return Verify() && Unzip() && BeginPatching();
-}
-
void ComponentUnpacker::Unpack(Callback callback) {
callback_ = std::move(callback);
- if (!UnpackInternal())
+ if (!Verify() || !BeginUnzipping())
EndUnpacking();
}
@@ -76,7 +72,7 @@
return true;
}
-bool ComponentUnpacker::Unzip() {
+bool ComponentUnpacker::BeginUnzipping() {
// Mind the reference to non-const type, passed as an argument below.
base::FilePath& destination = is_delta_ ? unpack_diff_path_ : unpack_path_;
if (!base::CreateNewTempDirectory(base::FilePath::StringType(),
@@ -86,13 +82,20 @@
return false;
}
VLOG(1) << "Unpacking in: " << destination.value();
- if (!zip::Unzip(path_, destination)) {
+ unzip::Unzip(connector_.get(), path_, destination,
+ base::BindOnce(&ComponentUnpacker::EndUnzipping, this));
+ return true;
+}
+
+void ComponentUnpacker::EndUnzipping(bool result) {
+ if (!result) {
VLOG(1) << "Unzipping failed.";
error_ = UnpackerError::kUnzipFailed;
- return false;
+ EndUnpacking();
+ return;
}
VLOG(1) << "Unpacked successfully";
- return true;
+ BeginPatching();
}
bool ComponentUnpacker::BeginPatching() {
diff --git a/components/update_client/component_unpacker.h b/components/update_client/component_unpacker.h
index 8a305dd..0fe5bcc9 100644
--- a/components/update_client/component_unpacker.h
+++ b/components/update_client/component_unpacker.h
@@ -96,16 +96,15 @@
virtual ~ComponentUnpacker();
- bool UnpackInternal();
-
// The first step of unpacking is to verify the file. Returns false if an
// error is encountered, the file is malformed, or the file is incorrectly
// signed.
bool Verify();
- // The second step of unpacking is to unzip. Returns false if an error
- // occurs as part of unzipping.
- bool Unzip();
+ // The second step of unpacking is to unzip. Returns false if an early error
+ // is encountered.
+ bool BeginUnzipping();
+ void EndUnzipping(bool error);
// The third step is to optionally patch files - this is a no-op for full
// (non-differential) updates. This step is asynchronous. Returns false if an
diff --git a/components/update_client/component_unpacker_unittest.cc b/components/update_client/component_unpacker_unittest.cc
index 3ba343c8..636ff68 100644
--- a/components/update_client/component_unpacker_unittest.cc
+++ b/components/update_client/component_unpacker_unittest.cc
@@ -100,10 +100,12 @@
}
TEST_F(ComponentUnpackerTest, UnpackFullCrx) {
+ auto config = base::MakeRefCounted<TestConfigurator>();
scoped_refptr<ComponentUnpacker> component_unpacker =
base::MakeRefCounted<ComponentUnpacker>(
std::vector<uint8_t>(std::begin(jebg_hash), std::end(jebg_hash)),
- test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"), nullptr, nullptr);
+ test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"), nullptr,
+ config->CreateServiceManagerConnector());
component_unpacker->Unpack(base::BindOnce(
&ComponentUnpackerTest::UnpackComplete, base::Unretained(this)));
RunThreads();
diff --git a/components/update_client/test_configurator.cc b/components/update_client/test_configurator.cc
index 2fde1dd5..1e28dd8 100644
--- a/components/update_client/test_configurator.cc
+++ b/components/update_client/test_configurator.cc
@@ -10,11 +10,20 @@
#include "base/version.h"
#include "components/patch_service/file_patcher_impl.h"
#include "components/patch_service/patch_service.h"
+#include "components/patch_service/public/interfaces/constants.mojom.h"
#include "components/patch_service/public/interfaces/file_patcher.mojom.h"
#include "components/prefs/pref_service.h"
+#include "components/unzip_service/public/interfaces/constants.mojom.h"
+#include "components/unzip_service/public/interfaces/unzipper.mojom.h"
+#include "components/unzip_service/unzip_service.h"
+#include "components/unzip_service/unzipper_impl.h"
#include "components/update_client/activity_data_service.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
#include "net/url_request/url_request_test_util.h"
#include "services/service_manager/public/cpp/connector.h"
+#include "services/service_manager/public/cpp/service.h"
+#include "services/service_manager/public/cpp/service_context.h"
+#include "services/service_manager/public/mojom/connector.mojom.h"
#include "url/gurl.h"
namespace update_client {
@@ -28,6 +37,93 @@
return urls;
}
+class TestConnector : public service_manager::mojom::Connector {
+ public:
+ TestConnector()
+ : patch_context_(std::make_unique<patch::PatchService>(),
+ mojo::MakeRequest(&patch_ptr_)),
+ unzip_context_(std::make_unique<unzip::UnzipService>(),
+ mojo::MakeRequest(&unzip_ptr_)) {
+ const service_manager::Identity service_id("TestConnector");
+ patch_ptr_->OnStart(service_id,
+ base::BindOnce(&TestConnector::OnStartCallback,
+ base::Unretained(this)));
+ unzip_ptr_->OnStart(service_id,
+ base::BindOnce(&TestConnector::OnStartCallback,
+ base::Unretained(this)));
+ }
+
+ ~TestConnector() override = default;
+
+ void BindInterface(const service_manager::Identity& target,
+ const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle interface_pipe,
+ BindInterfaceCallback callback) override {
+ service_manager::mojom::ServicePtr* service_ptr = nullptr;
+ if (interface_name == "patch::mojom::FilePatcher") {
+ service_ptr = &patch_ptr_;
+ } else if (interface_name == "unzip::mojom::Unzipper") {
+ service_ptr = &unzip_ptr_;
+ } else {
+ LOG(ERROR) << "Requested " << interface_name << " from the TestConnector"
+ << ", but no such instance was bound.";
+ return;
+ }
+ (*service_ptr)
+ ->OnBindInterface(service_manager::BindSourceInfo(
+ service_manager::Identity("TestConnector"),
+ service_manager::CapabilitySet()),
+ interface_name, std::move(interface_pipe),
+ base::BindRepeating(&base::DoNothing));
+ std::move(callback).Run(service_manager::mojom::ConnectResult::SUCCEEDED,
+ service_manager::Identity());
+ }
+
+ void StartService(const service_manager::Identity& target,
+ StartServiceCallback callback) override {
+ NOTREACHED();
+ }
+
+ void QueryService(const service_manager::Identity& target,
+ QueryServiceCallback callback) override {
+ NOTREACHED();
+ }
+
+ void StartServiceWithProcess(
+ const service_manager::Identity& identity,
+ mojo::ScopedMessagePipeHandle service,
+ service_manager::mojom::PIDReceiverRequest pid_receiver_request,
+ StartServiceWithProcessCallback callback) override {
+ NOTREACHED();
+ }
+
+ void Clone(service_manager::mojom::ConnectorRequest request) override {
+ bindings_.AddBinding(this, std::move(request));
+ }
+
+ void FilterInterfaces(
+ const std::string& spec,
+ const service_manager::Identity& source,
+ service_manager::mojom::InterfaceProviderRequest source_request,
+ service_manager::mojom::InterfaceProviderPtr target) override {
+ NOTREACHED();
+ }
+
+ private:
+ void OnStartCallback(
+ service_manager::mojom::ConnectorRequest request,
+ service_manager::mojom::ServiceControlAssociatedRequest control_request) {
+ }
+
+ service_manager::mojom::ServicePtr patch_ptr_;
+ service_manager::mojom::ServicePtr unzip_ptr_;
+ service_manager::ServiceContext patch_context_;
+ service_manager::ServiceContext unzip_context_;
+ mojo::BindingSet<service_manager::mojom::Connector> bindings_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestConnector);
+};
+
} // namespace
TestConfigurator::TestConfigurator()
@@ -36,12 +132,13 @@
ondemand_time_(0),
enabled_cup_signing_(false),
enabled_component_updates_(true),
- connector_factory_(
- service_manager::TestConnectorFactory::CreateForUniqueService(
- std::make_unique<patch::PatchService>())),
- connector_(connector_factory_->CreateConnector()),
+ connector_mojo_(base::MakeUnique<TestConnector>()),
context_(base::MakeRefCounted<net::TestURLRequestContextGetter>(
- base::ThreadTaskRunnerHandle::Get())) {}
+ base::ThreadTaskRunnerHandle::Get())) {
+ service_manager::mojom::ConnectorPtr proxy;
+ connector_mojo_->Clone(mojo::MakeRequest(&proxy));
+ connector_ = base::MakeUnique<service_manager::Connector>(std::move(proxy));
+}
TestConfigurator::~TestConfigurator() {
}
diff --git a/components/update_client/test_configurator.h b/components/update_client/test_configurator.h
index 9d12aa6..f4fc0db8 100644
--- a/components/update_client/test_configurator.h
+++ b/components/update_client/test_configurator.h
@@ -15,7 +15,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "components/update_client/configurator.h"
-#include "services/service_manager/public/cpp/test/test_connector_factory.h"
#include "url/gurl.h"
class PrefService;
@@ -26,8 +25,10 @@
} // namespace net
namespace service_manager {
+namespace mojom {
class Connector;
}
+} // namespace service_manager
namespace update_client {
@@ -122,7 +123,7 @@
GURL update_check_url_;
GURL ping_url_;
- std::unique_ptr<service_manager::TestConnectorFactory> connector_factory_;
+ std::unique_ptr<service_manager::mojom::Connector> connector_mojo_;
std::unique_ptr<service_manager::Connector> connector_;
scoped_refptr<net::TestURLRequestContextGetter> context_;
diff --git a/components/update_client/update_client_unittest.cc b/components/update_client/update_client_unittest.cc
index 9a8b533..efca391 100644
--- a/components/update_client/update_client_unittest.cc
+++ b/components/update_client/update_client_unittest.cc
@@ -3272,9 +3272,11 @@
base::RunLoop runloop;
base::OnceClosure quit_closure = runloop.QuitClosure();
+ auto config = base::MakeRefCounted<TestConfigurator>();
scoped_refptr<ComponentUnpacker> component_unpacker = new ComponentUnpacker(
std::vector<uint8_t>(std::begin(gjpm_hash), std::end(gjpm_hash)),
- TestFilePath("runaction_test_win.crx3"), nullptr, nullptr);
+ TestFilePath("runaction_test_win.crx3"), nullptr,
+ config->CreateServiceManagerConnector());
component_unpacker->Unpack(base::BindOnce(
[](base::FilePath* unpack_path, base::OnceClosure quit_closure,