Index: extensions/browser/sandboxed_unpacker.cc |
diff --git a/extensions/browser/sandboxed_unpacker.cc b/extensions/browser/sandboxed_unpacker.cc |
index 043dcd629576231049b486cd8baf1ccf59e29a88..d813fe8da779135a0f0269079a03ef0f2876316c 100644 |
--- a/extensions/browser/sandboxed_unpacker.cc |
+++ b/extensions/browser/sandboxed_unpacker.cc |
@@ -14,23 +14,19 @@ |
#include "base/command_line.h" |
#include "base/files/file_util.h" |
#include "base/json/json_string_value_serializer.h" |
-#include "base/message_loop/message_loop.h" |
#include "base/metrics/histogram_macros.h" |
-#include "base/numerics/safe_conversions.h" |
#include "base/path_service.h" |
#include "base/sequenced_task_runner.h" |
-#include "base/strings/string_number_conversions.h" |
#include "base/strings/utf_string_conversions.h" |
#include "base/threading/sequenced_worker_pool.h" |
#include "build/build_config.h" |
#include "components/crx_file/crx_file.h" |
#include "content/public/browser/browser_thread.h" |
-#include "content/public/browser/utility_process_host.h" |
-#include "content/public/common/common_param_traits.h" |
#include "extensions/common/constants.h" |
#include "extensions/common/extension.h" |
#include "extensions/common/extension_l10n_util.h" |
-#include "extensions/common/extension_utility_messages.h" |
+#include "extensions/common/extension_unpacker.mojom.h" |
+#include "extensions/common/extension_utility_types.h" |
#include "extensions/common/extensions_client.h" |
#include "extensions/common/file_util.h" |
#include "extensions/common/manifest_constants.h" |
@@ -43,7 +39,6 @@ |
using base::ASCIIToUTF16; |
using content::BrowserThread; |
-using content::UtilityProcessHost; |
using crx_file::CrxFile; |
// The following macro makes histograms that record the length of paths |
@@ -224,11 +219,9 @@ SandboxedUnpacker::SandboxedUnpacker( |
SandboxedUnpackerClient* client) |
: client_(client), |
extensions_dir_(extensions_dir), |
- got_response_(false), |
location_(location), |
creation_flags_(creation_flags), |
- unpacker_io_task_runner_(unpacker_io_task_runner), |
- utility_wrapper_(new UtilityHostWrapper) { |
+ unpacker_io_task_runner_(unpacker_io_task_runner) { |
// Tracking for crbug.com/692069. The location must be valid. If it's invalid, |
// the utility process kills itself for a bad IPC. |
CHECK_GT(location, Manifest::INVALID_LOCATION); |
@@ -318,8 +311,8 @@ void SandboxedUnpacker::StartWithCrx(const CRXFileInfo& crx_info) { |
link_free_crx_path); |
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
- base::Bind(&SandboxedUnpacker::StartUnzipOnIOThread, |
- this, link_free_crx_path)); |
+ base::Bind(&SandboxedUnpacker::UnzipOnIOThread, this, |
+ link_free_crx_path)); |
} |
void SandboxedUnpacker::StartWithDirectory(const std::string& extension_id, |
@@ -342,9 +335,9 @@ void SandboxedUnpacker::StartWithDirectory(const std::string& extension_id, |
return; |
} |
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
- base::Bind(&SandboxedUnpacker::StartUnpackOnIOThread, |
- this, extension_root_)); |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&SandboxedUnpacker::UnpackOnIOThread, this, extension_root_)); |
} |
SandboxedUnpacker::~SandboxedUnpacker() { |
@@ -353,28 +346,28 @@ SandboxedUnpacker::~SandboxedUnpacker() { |
temp_dir_.Take(); |
} |
-bool SandboxedUnpacker::OnMessageReceived(const IPC::Message& message) { |
- bool handled = true; |
- IPC_BEGIN_MESSAGE_MAP(SandboxedUnpacker, message) |
- IPC_MESSAGE_HANDLER(ExtensionUtilityHostMsg_UnzipToDir_Succeeded, |
- OnUnzipToDirSucceeded) |
- IPC_MESSAGE_HANDLER(ExtensionUtilityHostMsg_UnzipToDir_Failed, |
- OnUnzipToDirFailed) |
- IPC_MESSAGE_HANDLER(ExtensionUtilityHostMsg_UnpackExtension_Succeeded, |
- OnUnpackExtensionSucceeded) |
- IPC_MESSAGE_HANDLER(ExtensionUtilityHostMsg_UnpackExtension_Failed, |
- OnUnpackExtensionFailed) |
- IPC_MESSAGE_UNHANDLED(handled = false) |
- IPC_END_MESSAGE_MAP() |
- return handled; |
-} |
+void SandboxedUnpacker::StartUtilityProcessIfNeeded() { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
-void SandboxedUnpacker::OnProcessCrashed(int exit_code) { |
- // Don't report crashes if they happen after we got a response. |
- if (got_response_) |
+ if (utility_process_mojo_client_) |
return; |
- // Utility process crashed while trying to install. |
+ utility_process_mojo_client_ = base::MakeUnique< |
+ content::UtilityProcessMojoClient<mojom::ExtensionUnpacker>>( |
+ l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_EXTENSION_UNPACKER_NAME)); |
+ utility_process_mojo_client_->set_error_callback( |
+ base::Bind(&SandboxedUnpacker::UtilityProcessCrashed, this)); |
+ |
+ utility_process_mojo_client_->set_exposed_directory(temp_dir_.GetPath()); |
+ |
+ utility_process_mojo_client_->Start(); |
+} |
+ |
+void SandboxedUnpacker::UtilityProcessCrashed() { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
+ |
+ utility_process_mojo_client_.reset(); |
+ |
ReportFailure( |
UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL, |
l10n_util::GetStringFUTF16( |
@@ -384,60 +377,73 @@ void SandboxedUnpacker::OnProcessCrashed(int exit_code) { |
l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_PROCESS_CRASHED)); |
} |
-void SandboxedUnpacker::StartUnzipOnIOThread(const base::FilePath& crx_path) { |
- if (!utility_wrapper_->StartIfNeeded(temp_dir_.GetPath(), this, |
- unpacker_io_task_runner_)) { |
- ReportFailure( |
- COULD_NOT_START_UTILITY_PROCESS, |
- l10n_util::GetStringFUTF16( |
- IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
- FailureReasonToString16(COULD_NOT_START_UTILITY_PROCESS))); |
- return; |
- } |
+void SandboxedUnpacker::UnzipOnIOThread(const base::FilePath& crx_path) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ StartUtilityProcessIfNeeded(); |
+ |
DCHECK(crx_path.DirName() == temp_dir_.GetPath()); |
base::FilePath unzipped_dir = |
crx_path.DirName().AppendASCII(kTempExtensionName); |
- utility_wrapper_->host()->Send( |
- new ExtensionUtilityMsg_UnzipToDir(crx_path, unzipped_dir)); |
+ |
+ utility_process_mojo_client_->service()->Unzip( |
+ crx_path, unzipped_dir, |
+ base::Bind(&SandboxedUnpacker::UnzipDone, this, unzipped_dir)); |
} |
-void SandboxedUnpacker::StartUnpackOnIOThread( |
- const base::FilePath& directory_path) { |
- if (!utility_wrapper_->StartIfNeeded(temp_dir_.GetPath(), this, |
- unpacker_io_task_runner_)) { |
- ReportFailure( |
- COULD_NOT_START_UTILITY_PROCESS, |
- l10n_util::GetStringFUTF16( |
- IDS_EXTENSION_PACKAGE_INSTALL_ERROR, |
- FailureReasonToString16(COULD_NOT_START_UTILITY_PROCESS))); |
+void SandboxedUnpacker::UnzipDone(const base::FilePath& directory, |
+ bool success) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ if (!success) { |
+ utility_process_mojo_client_.reset(); |
+ ReportFailure(UNZIP_FAILED, |
+ l10n_util::GetStringUTF16(IDS_EXTENSION_PACKAGE_UNZIP_ERROR)); |
return; |
} |
- DCHECK(directory_path.DirName() == temp_dir_.GetPath()); |
- utility_wrapper_->host()->Send(new ExtensionUtilityMsg_UnpackExtension( |
- directory_path, extension_id_, location_, creation_flags_)); |
-} |
-void SandboxedUnpacker::OnUnzipToDirSucceeded(const base::FilePath& directory) { |
BrowserThread::PostTask( |
BrowserThread::IO, FROM_HERE, |
- base::Bind(&SandboxedUnpacker::StartUnpackOnIOThread, this, directory)); |
+ base::Bind(&SandboxedUnpacker::UnpackOnIOThread, this, directory)); |
} |
-void SandboxedUnpacker::OnUnzipToDirFailed(const std::string& error) { |
- got_response_ = true; |
- utility_wrapper_ = nullptr; |
- ReportFailure(UNZIP_FAILED, |
- l10n_util::GetStringUTF16(IDS_EXTENSION_PACKAGE_UNZIP_ERROR)); |
+void SandboxedUnpacker::UnpackOnIOThread(const base::FilePath& directory) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ StartUtilityProcessIfNeeded(); |
+ |
+ DCHECK(directory.DirName() == temp_dir_.GetPath()); |
+ |
+ utility_process_mojo_client_->service()->Unpack( |
+ directory, extension_id_, location_, creation_flags_, |
+ base::Bind(&SandboxedUnpacker::UnpackDone, this)); |
} |
-void SandboxedUnpacker::OnUnpackExtensionSucceeded( |
- const base::DictionaryValue& manifest) { |
+void SandboxedUnpacker::UnpackDone( |
+ const base::string16& error, |
+ std::unique_ptr<base::DictionaryValue> manifest) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ |
+ utility_process_mojo_client_.reset(); |
+ |
+ if (!error.empty()) { |
+ unpacker_io_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&SandboxedUnpacker::UnpackExtensionFailed, this, error)); |
+ return; |
+ } |
+ |
+ unpacker_io_task_runner_->PostTask( |
+ FROM_HERE, base::Bind(&SandboxedUnpacker::UnpackExtensionSucceeded, this, |
+ base::Passed(&manifest))); |
+} |
+ |
+void SandboxedUnpacker::UnpackExtensionSucceeded( |
+ std::unique_ptr<base::DictionaryValue> manifest) { |
CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); |
- got_response_ = true; |
- utility_wrapper_ = nullptr; |
std::unique_ptr<base::DictionaryValue> final_manifest( |
- RewriteManifestFile(manifest)); |
+ RewriteManifestFile(*manifest)); |
if (!final_manifest) |
return; |
@@ -477,13 +483,12 @@ void SandboxedUnpacker::OnUnpackExtensionSucceeded( |
if (!RewriteCatalogFiles()) |
return; |
- ReportSuccess(manifest, install_icon); |
+ ReportSuccess(std::move(manifest), install_icon); |
} |
-void SandboxedUnpacker::OnUnpackExtensionFailed(const base::string16& error) { |
+void SandboxedUnpacker::UnpackExtensionFailed(const base::string16& error) { |
CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread()); |
- got_response_ = true; |
- utility_wrapper_ = nullptr; |
+ |
ReportFailure( |
UNPACKER_CLIENT_FAILED, |
l10n_util::GetStringFUTF16(IDS_EXTENSION_PACKAGE_ERROR_MESSAGE, error)); |
@@ -572,13 +577,12 @@ base::string16 SandboxedUnpacker::FailureReasonToString16( |
return ASCIIToUTF16("UNZIP_FAILED"); |
case DIRECTORY_MOVE_FAILED: |
return ASCIIToUTF16("DIRECTORY_MOVE_FAILED"); |
- case COULD_NOT_START_UTILITY_PROCESS: |
- return ASCIIToUTF16("COULD_NOT_START_UTILITY_PROCESS"); |
case NUM_FAILURE_REASONS: |
NOTREACHED(); |
return base::string16(); |
} |
+ |
NOTREACHED(); |
return base::string16(); |
} |
@@ -648,7 +652,6 @@ bool SandboxedUnpacker::ValidateSignature(const base::FilePath& crx_path, |
void SandboxedUnpacker::ReportFailure(FailureReason reason, |
const base::string16& error) { |
- utility_wrapper_ = nullptr; |
UMA_HISTOGRAM_ENUMERATION("Extensions.SandboxUnpackFailureReason", reason, |
NUM_FAILURE_REASONS); |
if (!crx_unpack_start_time_.is_null()) |
@@ -665,9 +668,8 @@ void SandboxedUnpacker::ReportFailure(FailureReason reason, |
} |
void SandboxedUnpacker::ReportSuccess( |
- const base::DictionaryValue& original_manifest, |
+ const std::unique_ptr<base::DictionaryValue>& original_manifest, |
const SkBitmap& install_icon) { |
- utility_wrapper_ = nullptr; |
UMA_HISTOGRAM_COUNTS("Extensions.SandboxUnpackSuccess", 1); |
if (!crx_unpack_start_time_.is_null()) |
@@ -677,8 +679,11 @@ void SandboxedUnpacker::ReportSuccess( |
DCHECK(!temp_dir_.GetPath().empty()); |
// Client takes ownership of temporary directory and extension. |
+ // TODO(https://crbug.com/699528): we should consider transferring the |
+ // ownership of original_manifest to our clients as well. |
client_->OnUnpackSuccess(temp_dir_.Take(), extension_root_, |
- &original_manifest, extension_.get(), install_icon); |
+ original_manifest.get(), extension_.get(), |
+ install_icon); |
extension_ = NULL; |
} |
@@ -898,42 +903,4 @@ void SandboxedUnpacker::Cleanup() { |
} |
} |
-SandboxedUnpacker::UtilityHostWrapper::UtilityHostWrapper() {} |
- |
-bool SandboxedUnpacker::UtilityHostWrapper::StartIfNeeded( |
- const base::FilePath& exposed_dir, |
- const scoped_refptr<UtilityProcessHostClient>& client, |
- const scoped_refptr<base::SequencedTaskRunner>& client_task_runner) { |
- DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- if (!utility_host_) { |
- utility_host_ = |
- UtilityProcessHost::Create(client, client_task_runner)->AsWeakPtr(); |
- utility_host_->SetName( |
- l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_EXTENSION_UNPACKER_NAME)); |
- |
- // Grant the subprocess access to our temp dir so it can write out files. |
- DCHECK(!exposed_dir.empty()); |
- utility_host_->SetExposedDir(exposed_dir); |
- if (!utility_host_->StartBatchMode()) { |
- utility_host_.reset(); |
- return false; |
- } |
- } |
- return true; |
-} |
- |
-content::UtilityProcessHost* SandboxedUnpacker::UtilityHostWrapper::host() |
- const { |
- DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- return utility_host_.get(); |
-} |
- |
-SandboxedUnpacker::UtilityHostWrapper::~UtilityHostWrapper() { |
- DCHECK_CURRENTLY_ON(BrowserThread::IO); |
- if (utility_host_) { |
- utility_host_->EndBatchMode(); |
- utility_host_.reset(); |
- } |
-} |
- |
} // namespace extensions |