summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorzelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-15 19:40:14 +0000
committerzelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-15 19:40:14 +0000
commit7f8f24fef695dbf71762bb2f376d95d8b9669bc4 (patch)
tree63ec27091b54d2aaf7dc0cf4728ba4115b40010d /chrome
parentf170405cfa52c48c9b8a8e0113f02887c1ff7f9a (diff)
downloadchromium_src-7f8f24fef695dbf71762bb2f376d95d8b9669bc4.zip
chromium_src-7f8f24fef695dbf71762bb2f376d95d8b9669bc4.tar.gz
chromium_src-7f8f24fef695dbf71762bb2f376d95d8b9669bc4.tar.bz2
Moved extension installation from FILE thread. CrxInstaller and friends are now using their own sequenced task runner instead.
BUG=160183 TEST=SandboxedUnpackerTest.*, ExtensionInstallUIBrowserTest.* Review URL: https://codereview.chromium.org/11369146 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@167991 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/chromeos/kiosk_mode/kiosk_mode_screensaver.cc2
-rw-r--r--chrome/browser/component_updater/component_updater_service.cc3
-rw-r--r--chrome/browser/extensions/api/management/management_api.cc4
-rw-r--r--chrome/browser/extensions/crx_installer.cc77
-rw-r--r--chrome/browser/extensions/crx_installer.h15
-rw-r--r--chrome/browser/extensions/extension_service.cc38
-rw-r--r--chrome/browser/extensions/extension_service.h14
-rw-r--r--chrome/browser/extensions/extension_service_unittest.cc4
-rw-r--r--chrome/browser/extensions/sandboxed_unpacker.cc31
-rw-r--r--chrome/browser/extensions/sandboxed_unpacker.h11
-rw-r--r--chrome/browser/extensions/sandboxed_unpacker_unittest.cc11
-rw-r--r--chrome/browser/extensions/test_extension_service.cc5
-rw-r--r--chrome/browser/extensions/test_extension_service.h2
-rw-r--r--chrome/browser/extensions/updater/safe_manifest_parser.cc2
-rw-r--r--chrome/browser/extensions/webstore_install_helper.cc3
-rw-r--r--chrome/browser/extensions/webstore_standalone_installer.cc3
-rw-r--r--chrome/browser/image_decoder.cc2
-rw-r--r--chrome/browser/importer/external_process_importer_client.cc4
-rw-r--r--chrome/browser/themes/browser_theme_pack.cc6
-rw-r--r--chrome/browser/themes/theme_service.cc14
-rw-r--r--chrome/browser/web_resource/json_asynchronous_unpacker.cc3
21 files changed, 177 insertions, 77 deletions
diff --git a/chrome/browser/chromeos/kiosk_mode/kiosk_mode_screensaver.cc b/chrome/browser/chromeos/kiosk_mode/kiosk_mode_screensaver.cc
index 1e4428d..5edee1a 100644
--- a/chrome/browser/chromeos/kiosk_mode/kiosk_mode_screensaver.cc
+++ b/chrome/browser/chromeos/kiosk_mode/kiosk_mode_screensaver.cc
@@ -188,6 +188,8 @@ void KioskModeScreensaver::ScreensaverPathCallback(
Extension::COMPONENT,
Extension::NO_FLAGS,
extensions_dir,
+ content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::FILE),
new ScreensaverUnpackerClient(
screensaver_crx,
base::Bind(
diff --git a/chrome/browser/component_updater/component_updater_service.cc b/chrome/browser/component_updater/component_updater_service.cc
index b141a42..654b9cb 100644
--- a/chrome/browser/component_updater/component_updater_service.cc
+++ b/chrome/browser/component_updater/component_updater_service.cc
@@ -605,7 +605,8 @@ void CrxUpdateService::ParseManifest(const std::string& xml) {
}
} else {
UtilityProcessHost* host = UtilityProcessHost::Create(
- new ManifestParserBridge(this), BrowserThread::UI);
+ new ManifestParserBridge(this),
+ base::MessageLoopProxy::current());
host->EnableZygote();
host->Send(new ChromeUtilityMsg_ParseUpdateManifest(xml));
}
diff --git a/chrome/browser/extensions/api/management/management_api.cc b/chrome/browser/extensions/api/management/management_api.cc
index 58ec543..d934b99 100644
--- a/chrome/browser/extensions/api/management/management_api.cc
+++ b/chrome/browser/extensions/api/management/management_api.cc
@@ -290,7 +290,9 @@ class SafeManifestJSONParser : public UtilityProcessHostClient {
void StartWorkOnIOThread() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
UtilityProcessHost* host =
- UtilityProcessHost::Create(this, BrowserThread::IO);
+ UtilityProcessHost::Create(
+ this,
+ base::MessageLoopProxy::current());
host->EnableZygote();
host->Send(new ChromeUtilityMsg_ParseJSON(manifest_));
}
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index 0ee089b..3c8354c 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -13,10 +13,12 @@
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/scoped_temp_dir.h"
+#include "base/sequenced_task_runner.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "base/time.h"
+#include "base/threading/sequenced_worker_pool.h"
#include "base/utf_string_conversions.h"
#include "base/version.h"
#include "chrome/browser/browser_process.h"
@@ -105,6 +107,7 @@ CrxInstaller::CrxInstaller(
requirements_checker_(new extensions::RequirementsChecker()),
has_requirement_errors_(false),
install_wait_for_idle_(true) {
+ installer_task_runner_ = frontend_weak->GetFileTaskRunner();
if (!approval)
return;
@@ -128,19 +131,6 @@ CrxInstaller::CrxInstaller(
}
CrxInstaller::~CrxInstaller() {
- // Delete the temp directory and crx file as necessary. Note that the
- // destructor might be called on any thread, so we post a task to the file
- // thread to make sure the delete happens there. This is a best effort
- // operation since the browser can be shutting down so there might not
- // be a file thread to post to.
- if (!temp_dir_.value().empty()) {
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&extension_file_util::DeleteFile, temp_dir_, true));
- }
- if (delete_source_) {
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&extension_file_util::DeleteFile, source_file_, false));
- }
// Make sure the UI is deleted on the ui thread.
if (client_) {
BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, client_);
@@ -158,10 +148,11 @@ void CrxInstaller::InstallCrx(const FilePath& source_file) {
install_source_,
creation_flags_,
install_directory_,
+ installer_task_runner_,
this));
- if (!BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
+ if (!installer_task_runner_->PostTask(
+ FROM_HERE,
base::Bind(&SandboxedUnpacker::Start, unpacker.get())))
NOTREACHED();
}
@@ -173,8 +164,8 @@ void CrxInstaller::InstallUserScript(const FilePath& source_file,
source_file_ = source_file;
download_url_ = download_url;
- if (!BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
+ if (!installer_task_runner_->PostTask(
+ FROM_HERE,
base::Bind(&CrxInstaller::ConvertUserScriptOnFileThread, this)))
NOTREACHED();
}
@@ -192,8 +183,8 @@ void CrxInstaller::ConvertUserScriptOnFileThread() {
}
void CrxInstaller::InstallWebApp(const WebApplicationInfo& web_app) {
- if (!BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
+ if (!installer_task_runner_->PostTask(
+ FROM_HERE,
base::Bind(&CrxInstaller::ConvertWebAppOnFileThread,
this,
web_app,
@@ -218,7 +209,7 @@ void CrxInstaller::ConvertWebAppOnFileThread(
}
CrxInstallerError CrxInstaller::AllowInstall(const Extension* extension) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(installer_task_runner_->RunsTasksOnCurrentThread());
// Make sure the expected ID matches if one was supplied or if we want to
// bypass the prompt.
@@ -347,7 +338,7 @@ CrxInstallerError CrxInstaller::AllowInstall(const Extension* extension) {
}
void CrxInstaller::OnUnpackFailure(const string16& error_message) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(installer_task_runner_->RunsTasksOnCurrentThread());
UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackFailureInstallSource",
install_source(), Extension::NUM_LOCATIONS);
@@ -363,7 +354,7 @@ void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir,
const FilePath& extension_dir,
const DictionaryValue* original_manifest,
const Extension* extension) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(installer_task_runner_->RunsTasksOnCurrentThread());
UMA_HISTOGRAM_ENUMERATION("Extensions.UnpackSuccessInstallSource",
install_source(), Extension::NUM_LOCATIONS);
@@ -462,8 +453,8 @@ void CrxInstaller::ConfirmInstall() {
AddRef(); // Balanced in Proceed() and Abort().
client_->ConfirmInstall(this, extension_.get(), show_dialog_callback_);
} else {
- if (!BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
+ if (!installer_task_runner_->PostTask(
+ FROM_HERE,
base::Bind(&CrxInstaller::CompleteInstall, this)))
NOTREACHED();
}
@@ -471,8 +462,8 @@ void CrxInstaller::ConfirmInstall() {
}
void CrxInstaller::InstallUIProceed() {
- if (!BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
+ if (!installer_task_runner_->PostTask(
+ FROM_HERE,
base::Bind(&CrxInstaller::CompleteInstall, this)))
NOTREACHED();
@@ -502,7 +493,7 @@ void CrxInstaller::InstallUIAbort(bool user_initiated) {
}
void CrxInstaller::CompleteInstall() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(installer_task_runner_->RunsTasksOnCurrentThread());
if (!current_version_.empty()) {
Version current_version(current_version_);
@@ -561,7 +552,7 @@ void CrxInstaller::CompleteInstall() {
}
void CrxInstaller::ReportFailureFromFileThread(const CrxInstallerError& error) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(installer_task_runner_->RunsTasksOnCurrentThread());
if (!BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&CrxInstaller::ReportFailureFromUIThread, this, error))) {
@@ -590,10 +581,13 @@ void CrxInstaller::ReportFailureFromUIThread(const CrxInstallerError& error) {
client_->OnInstallFailure(error);
NotifyCrxInstallComplete(NULL);
+
+ // Delete temporary files.
+ CleanupTempFiles();
}
void CrxInstaller::ReportSuccessFromFileThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(installer_task_runner_->RunsTasksOnCurrentThread());
// Tracking number of extensions installed by users
if (install_cause() == extension_misc::INSTALL_CAUSE_USER_DOWNLOAD)
@@ -603,6 +597,9 @@ void CrxInstaller::ReportSuccessFromFileThread() {
BrowserThread::UI, FROM_HERE,
base::Bind(&CrxInstaller::ReportSuccessFromUIThread, this)))
NOTREACHED();
+
+ // Delete temporary files.
+ CleanupTempFiles();
}
void CrxInstaller::ReportSuccessFromUIThread() {
@@ -654,4 +651,26 @@ void CrxInstaller::NotifyCrxInstallComplete(const Extension* extension) {
content::Details<const Extension>(extension));
}
+void CrxInstaller::CleanupTempFiles() {
+ if (!installer_task_runner_->RunsTasksOnCurrentThread()) {
+ if (!installer_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&CrxInstaller::CleanupTempFiles, this))) {
+ NOTREACHED();
+ }
+ return;
+ }
+
+ // Delete the temp directory and crx file as necessary.
+ if (!temp_dir_.value().empty()) {
+ extension_file_util::DeleteFile(temp_dir_, true);
+ temp_dir_ = FilePath();
+ }
+
+ if (delete_source_ && !source_file_.value().empty()) {
+ extension_file_util::DeleteFile(source_file_, false);
+ source_file_ = FilePath();
+ }
+}
+
} // namespace extensions
diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h
index 5d2d195..0f0019f 100644
--- a/chrome/browser/extensions/crx_installer.h
+++ b/chrome/browser/extensions/crx_installer.h
@@ -21,8 +21,13 @@
#include "sync/api/string_ordinal.h"
class ExtensionService;
+class ExtensionServiceTest;
class SkBitmap;
+namespace base {
+class SequencedTaskRunner;
+}
+
namespace extensions {
class ExtensionUpdaterTest;
class RequirementsChecker;
@@ -184,6 +189,7 @@ class CrxInstaller
Profile* profile() { return profile_; }
private:
+ friend class ::ExtensionServiceTest;
friend class ExtensionUpdaterTest;
friend class ExtensionCrxInstallerTest;
@@ -235,6 +241,12 @@ class CrxInstaller
void ReportSuccessFromUIThread();
void NotifyCrxInstallComplete(const Extension* extension);
+ // Deletes temporary directory and crx file if needed.
+ void CleanupTempFiles();
+
+ // Creates sequenced task runner for extension install file I/O operations.
+ scoped_refptr<base::SequencedTaskRunner> CreateSequencedTaskRunner();
+
// The file we're installing.
FilePath source_file_;
@@ -371,6 +383,9 @@ class CrxInstaller
bool install_wait_for_idle_;
+ // Sequenced task runner where file I/O operations will be performed.
+ scoped_refptr<base::SequencedTaskRunner> installer_task_runner_;
+
// Used to show the install dialog.
ExtensionInstallPrompt::ShowDialogCallback show_dialog_callback_;
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 9499f21..4063742 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -19,6 +19,7 @@
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
+#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
@@ -243,6 +244,11 @@ void ExtensionService::CheckExternalUninstall(const std::string& id) {
UninstallExtension(id, true, NULL);
}
+void ExtensionService::SetFileTaskRunnerForTesting(
+ base::SequencedTaskRunner* task_runner) {
+ file_task_runner_ = task_runner;
+}
+
void ExtensionService::ClearProvidersForTesting() {
external_extension_providers_.clear();
}
@@ -634,8 +640,8 @@ bool ExtensionService::UpdateExtension(const std::string& id,
<< " because it is not installed or pending";
// Delete extension_path since we're not creating a CrxInstaller
// that would do it for us.
- if (!BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
+ if (!GetFileTaskRunner()->PostTask(
+ FROM_HERE,
base::Bind(
&extension_file_util::DeleteFile, extension_path, false)))
NOTREACHED();
@@ -826,8 +832,8 @@ bool ExtensionService::UninstallExtension(
// Tell the backend to start deleting installed extensions on the file thread.
if (Extension::LOAD != extension->location()) {
- if (!BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
+ if (!GetFileTaskRunner()->PostTask(
+ FROM_HERE,
base::Bind(
&extension_file_util::UninstallExtension,
install_directory_,
@@ -1238,6 +1244,22 @@ bool ExtensionService::is_ready() {
return ready_;
}
+base::SequencedTaskRunner* ExtensionService::GetFileTaskRunner() {
+ if (file_task_runner_)
+ return file_task_runner_;
+
+ // We should be able to interrupt any part of extension install process during
+ // shutdown. SKIP_ON_SHUTDOWN ensures that not started extension install tasks
+ // will be ignored/deleted while we will block on started tasks.
+ std::string token("ext_install-");
+ token.append(profile_->GetPath().AsUTF8Unsafe());
+ file_task_runner_ = BrowserThread::GetBlockingPool()->
+ GetSequencedTaskRunnerWithShutdownBehavior(
+ BrowserThread::GetBlockingPool()->GetNamedSequenceToken(token),
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+ return file_task_runner_;
+}
+
extensions::ExtensionUpdater* ExtensionService::updater() {
return updater_.get();
}
@@ -1982,8 +2004,8 @@ void ExtensionService::GarbageCollectExtensions() {
extension_paths.insert(std::make_pair(info->at(i)->extension_id,
info->at(i)->extension_path));
- if (!BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
+ if (!GetFileTaskRunner()->PostTask(
+ FROM_HERE,
base::Bind(
&extension_file_util::GarbageCollectExtensions,
install_directory_,
@@ -2284,8 +2306,8 @@ void ExtensionService::OnExtensionInstalled(
// Delete the extension directory since we're not going to
// load it.
- if (!BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
+ if (!GetFileTaskRunner()->PostTask(
+ FROM_HERE,
base::Bind(&extension_file_util::DeleteFile,
extension->path(), true))) {
NOTREACHED();
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 23ef9aa..23542e9 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -50,6 +50,10 @@ class GURL;
class Profile;
class Version;
+namespace base {
+class SequencedTaskRunner;
+}
+
namespace chromeos {
class ExtensionInputMethodEventRouter;
}
@@ -132,6 +136,9 @@ class ExtensionServiceInterface : public syncer::SyncableService {
const extensions::Extension& extension) = 0;
virtual bool is_ready() = 0;
+
+ // Returns task runner for crx installation file I/O operations.
+ virtual base::SequencedTaskRunner* GetFileTaskRunner() = 0;
};
// Manages installed and running Chromium extensions.
@@ -509,6 +516,8 @@ class ExtensionService
// Whether the extension service is ready.
virtual bool is_ready() OVERRIDE;
+ virtual base::SequencedTaskRunner* GetFileTaskRunner() OVERRIDE;
+
extensions::ComponentLoader* component_loader() {
return component_loader_.get();
}
@@ -561,6 +570,9 @@ class ExtensionService
// externally managed extension. If so, uninstall it.
void CheckExternalUninstall(const std::string& id);
+ // Changes sequenced task runner for crx installation tasks to |task_runner|.
+ void SetFileTaskRunnerForTesting(base::SequencedTaskRunner* task_runner);
+
// Clear all ExternalProviders.
void ClearProvidersForTesting();
@@ -955,6 +967,8 @@ class ExtensionService
extensions::AppShortcutManager app_shortcut_manager_;
scoped_ptr<ExtensionErrorUI> extension_error_ui_;
+ // Sequenced task runner for extension related file operations.
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
#if defined(ENABLE_EXTENSIONS)
scoped_ptr<extensions::ExtensionActionStorageManager>
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 007dcd3..0793270 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -436,6 +436,7 @@ void ExtensionServiceTestBase::InitializeExtensionService(
CommandLine::ForCurrentProcess(),
extensions_install_dir,
autoupdate_enabled);
+ service_->SetFileTaskRunnerForTesting(loop_.message_loop_proxy());
service_->set_extensions_enabled(true);
service_->set_show_extensions_prompts(false);
service_->set_install_updates_when_idle_for_test(false);
@@ -679,7 +680,6 @@ class ExtensionServiceTest
<< "Path does not exist: "<< crx_path.value().c_str();
// no client (silent install)
scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
-
installer->set_install_source(install_location);
installer->InstallCrx(crx_path);
@@ -5814,7 +5814,7 @@ TEST_F(ExtensionServiceTest, WipeOutExtension) {
data_dir_.AppendASCII("good.crx"));
service_->CheckForExternalUpdates();
- loop_.RunAllPending();
+ loop_.RunUntilIdle();
EXPECT_FALSE(extensions::HasExternalInstallError(service_));
EXPECT_FALSE(service_->IsExtensionEnabled(good_crx));
EXPECT_TRUE(service_->IsExtensionEnabled(page_action));
diff --git a/chrome/browser/extensions/sandboxed_unpacker.cc b/chrome/browser/extensions/sandboxed_unpacker.cc
index a9a9179..f1d4c88 100644
--- a/chrome/browser/extensions/sandboxed_unpacker.cc
+++ b/chrome/browser/extensions/sandboxed_unpacker.cc
@@ -16,6 +16,7 @@
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
+#include "base/sequenced_task_runner.h"
#include "base/utf_string_conversions.h" // TODO(viettrungluu): delete me.
#include "chrome/browser/extensions/crx_file.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -177,19 +178,20 @@ SandboxedUnpacker::SandboxedUnpacker(
Extension::Location location,
int creation_flags,
const FilePath& extensions_dir,
+ base::SequencedTaskRunner* unpacker_io_task_runner,
SandboxedUnpackerClient* client)
: crx_path_(crx_path),
- thread_identifier_(BrowserThread::ID_COUNT),
run_out_of_process_(run_out_of_process),
client_(client),
extensions_dir_(extensions_dir),
got_response_(false),
location_(location),
- creation_flags_(creation_flags) {
+ creation_flags_(creation_flags),
+ unpacker_io_task_runner_(unpacker_io_task_runner) {
}
bool SandboxedUnpacker::CreateTempDirectory() {
- CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_identifier_));
+ CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread());
FilePath temp_dir;
if (!FindWritableTempLocation(extensions_dir_, &temp_dir)) {
@@ -216,7 +218,7 @@ bool SandboxedUnpacker::CreateTempDirectory() {
void SandboxedUnpacker::Start() {
// We assume that we are started on the thread that the client wants us to do
// file IO on.
- CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_identifier_));
+ CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread());
unpack_start_time_ = base::TimeTicks::Now();
@@ -293,9 +295,6 @@ void SandboxedUnpacker::Start() {
}
SandboxedUnpacker::~SandboxedUnpacker() {
- base::FileUtilProxy::Delete(
- BrowserThread::GetMessageLoopProxyForThread(thread_identifier_),
- temp_dir_.Take(), true, base::FileUtilProxy::StatusCallback());
}
bool SandboxedUnpacker::OnMessageReceived(const IPC::Message& message) {
@@ -325,7 +324,7 @@ void SandboxedUnpacker::OnProcessCrashed(int exit_code) {
void SandboxedUnpacker::StartProcessOnIOThread(const FilePath& temp_crx_path) {
UtilityProcessHost* host = UtilityProcessHost::Create(
- this, thread_identifier_);
+ this, unpacker_io_task_runner_);
// Grant the subprocess access to the entire subdir the extension file is
// in, so that it can unpack to that dir.
host->SetExposedDir(temp_crx_path.DirName());
@@ -336,9 +335,7 @@ void SandboxedUnpacker::StartProcessOnIOThread(const FilePath& temp_crx_path) {
void SandboxedUnpacker::OnUnpackExtensionSucceeded(
const DictionaryValue& manifest) {
- // Skip check for unittests.
- if (thread_identifier_ != BrowserThread::ID_COUNT)
- CHECK(BrowserThread::CurrentlyOn(thread_identifier_));
+ CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread());
got_response_ = true;
scoped_ptr<DictionaryValue> final_manifest(RewriteManifestFile(manifest));
@@ -391,7 +388,7 @@ void SandboxedUnpacker::OnUnpackExtensionSucceeded(
}
void SandboxedUnpacker::OnUnpackExtensionFailed(const string16& error) {
- CHECK(BrowserThread::CurrentlyOn(thread_identifier_));
+ CHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread());
got_response_ = true;
ReportFailure(
UNPACKER_CLIENT_FAILED,
@@ -569,7 +566,7 @@ void SandboxedUnpacker::ReportFailure(FailureReason reason,
reason, NUM_FAILURE_REASONS);
UMA_HISTOGRAM_TIMES("Extensions.SandboxUnpackFailureTime",
base::TimeTicks::Now() - unpack_start_time_);
-
+ Cleanup();
client_->OnUnpackFailure(error);
}
@@ -792,4 +789,12 @@ bool SandboxedUnpacker::RewriteCatalogFiles() {
return true;
}
+void SandboxedUnpacker::Cleanup() {
+ DCHECK(unpacker_io_task_runner_->RunsTasksOnCurrentThread());
+ if (!temp_dir_.Delete()) {
+ LOG(WARNING) << "Can not delete temp directory at "
+ << temp_dir_.path().value();
+ }
+}
+
} // namespace extensions
diff --git a/chrome/browser/extensions/sandboxed_unpacker.h b/chrome/browser/extensions/sandboxed_unpacker.h
index 22abb5f..67af256 100644
--- a/chrome/browser/extensions/sandboxed_unpacker.h
+++ b/chrome/browser/extensions/sandboxed_unpacker.h
@@ -16,6 +16,7 @@
namespace base {
class DictionaryValue;
+class SequencedTaskRunner;
}
namespace extensions {
@@ -77,6 +78,7 @@ class SandboxedUnpacker : public content::UtilityProcessHostClient {
Extension::Location location,
int creation_flags,
const FilePath& extensions_dir,
+ base::SequencedTaskRunner* unpacker_io_task_runner,
SandboxedUnpackerClient* client);
// Start unpacking the extension. The client is called with the results.
@@ -187,12 +189,12 @@ class SandboxedUnpacker : public content::UtilityProcessHostClient {
bool RewriteImageFiles();
bool RewriteCatalogFiles();
+ // Cleans up temp directory artifacts.
+ void Cleanup();
+
// The path to the CRX to unpack.
FilePath crx_path_;
- // Our client's thread. This is the thread we respond on.
- content::BrowserThread::ID thread_identifier_;
-
// True if unpacking should be done by the utility process.
bool run_out_of_process_;
@@ -230,6 +232,9 @@ class SandboxedUnpacker : public content::UtilityProcessHostClient {
// Creation flags to use for the extension. These flags will be used
// when calling Extenion::Create() by the crx installer.
int creation_flags_;
+
+ // Sequenced task runner where file I/O operations will be performed at.
+ scoped_refptr<base::SequencedTaskRunner> unpacker_io_task_runner_;
};
} // namespace extensions
diff --git a/chrome/browser/extensions/sandboxed_unpacker_unittest.cc b/chrome/browser/extensions/sandboxed_unpacker_unittest.cc
index c16f325..11c4dd1 100644
--- a/chrome/browser/extensions/sandboxed_unpacker_unittest.cc
+++ b/chrome/browser/extensions/sandboxed_unpacker_unittest.cc
@@ -104,13 +104,12 @@ class SandboxedUnpackerTest : public testing::Test {
ASSERT_TRUE(file_util::CreateDirectory(temp_path_));
sandboxed_unpacker_ =
- new SandboxedUnpacker(crx_path, false, Extension::INTERNAL,
- Extension::NO_FLAGS, extensions_dir_.path(),
- client_);
+ new SandboxedUnpacker(
+ crx_path, false, Extension::INTERNAL, Extension::NO_FLAGS,
+ extensions_dir_.path(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
+ client_);
- // Hack since SandboxedUnpacker gets its background thread id from
- // the Start call, but we don't call it here.
- sandboxed_unpacker_->thread_identifier_ = BrowserThread::FILE;
EXPECT_TRUE(PrepareUnpackerEnv());
}
diff --git a/chrome/browser/extensions/test_extension_service.cc b/chrome/browser/extensions/test_extension_service.cc
index 16d5bc2..46871cd 100644
--- a/chrome/browser/extensions/test_extension_service.cc
+++ b/chrome/browser/extensions/test_extension_service.cc
@@ -105,6 +105,11 @@ bool TestExtensionService::is_ready() {
return false;
}
+base::SequencedTaskRunner* TestExtensionService::GetFileTaskRunner() {
+ ADD_FAILURE();
+ return NULL;
+}
+
void TestExtensionService::AddExtension(const Extension* extension) {
ADD_FAILURE();
}
diff --git a/chrome/browser/extensions/test_extension_service.h b/chrome/browser/extensions/test_extension_service.h
index 0c0b27f..11b95e2 100644
--- a/chrome/browser/extensions/test_extension_service.h
+++ b/chrome/browser/extensions/test_extension_service.h
@@ -65,6 +65,8 @@ class TestExtensionService : public ExtensionServiceInterface {
virtual bool is_ready() OVERRIDE;
+ virtual base::SequencedTaskRunner* GetFileTaskRunner() OVERRIDE;
+
virtual void AddExtension(const extensions::Extension* extension) OVERRIDE;
virtual void UnloadExtension(
diff --git a/chrome/browser/extensions/updater/safe_manifest_parser.cc b/chrome/browser/extensions/updater/safe_manifest_parser.cc
index 7287122..920a2ff 100644
--- a/chrome/browser/extensions/updater/safe_manifest_parser.cc
+++ b/chrome/browser/extensions/updater/safe_manifest_parser.cc
@@ -51,7 +51,7 @@ void SafeManifestParser::ParseInSandbox() {
!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
if (use_utility_process) {
content::UtilityProcessHost* host = content::UtilityProcessHost::Create(
- this, BrowserThread::UI);
+ this, BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI));
host->EnableZygote();
host->Send(new ChromeUtilityMsg_ParseUpdateManifest(xml_));
} else {
diff --git a/chrome/browser/extensions/webstore_install_helper.cc b/chrome/browser/extensions/webstore_install_helper.cc
index 950fbb6..2b27dd5 100644
--- a/chrome/browser/extensions/webstore_install_helper.cc
+++ b/chrome/browser/extensions/webstore_install_helper.cc
@@ -74,7 +74,8 @@ void WebstoreInstallHelper::Start() {
void WebstoreInstallHelper::StartWorkOnIOThread() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
utility_host_ =
- UtilityProcessHost::Create(this, BrowserThread::IO)->AsWeakPtr();
+ UtilityProcessHost::Create(
+ this, base::MessageLoopProxy::current())->AsWeakPtr();
utility_host_->EnableZygote();
utility_host_->StartBatchMode();
diff --git a/chrome/browser/extensions/webstore_standalone_installer.cc b/chrome/browser/extensions/webstore_standalone_installer.cc
index bb3e38b..7686908 100644
--- a/chrome/browser/extensions/webstore_standalone_installer.cc
+++ b/chrome/browser/extensions/webstore_standalone_installer.cc
@@ -81,7 +81,8 @@ class SafeWebstoreResponseParser : public UtilityProcessHostClient {
void StartWorkOnIOThread() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
UtilityProcessHost* host =
- UtilityProcessHost::Create(this, BrowserThread::IO);
+ UtilityProcessHost::Create(
+ this, base::MessageLoopProxy::current());
host->EnableZygote();
host->Send(new ChromeUtilityMsg_ParseJSON(webstore_data_));
}
diff --git a/chrome/browser/image_decoder.cc b/chrome/browser/image_decoder.cc
index 1f456ee..6d7b948 100644
--- a/chrome/browser/image_decoder.cc
+++ b/chrome/browser/image_decoder.cc
@@ -62,7 +62,7 @@ void ImageDecoder::DecodeImageInSandbox(
const std::vector<unsigned char>& image_data) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
UtilityProcessHost* utility_process_host = UtilityProcessHost::Create(
- this, target_thread_id_);
+ this, BrowserThread::GetMessageLoopProxyForThread(target_thread_id_));
utility_process_host->EnableZygote();
if (image_codec_ == ROBUST_JPEG_CODEC) {
utility_process_host->Send(
diff --git a/chrome/browser/importer/external_process_importer_client.cc b/chrome/browser/importer/external_process_importer_client.cc
index 36dc21d..bcec842 100644
--- a/chrome/browser/importer/external_process_importer_client.cc
+++ b/chrome/browser/importer/external_process_importer_client.cc
@@ -261,7 +261,9 @@ void ExternalProcessImporterClient::NotifyItemFinishedOnIOThread(
void ExternalProcessImporterClient::StartProcessOnIOThread(
BrowserThread::ID thread_id) {
utility_process_host_ =
- UtilityProcessHost::Create(this, thread_id)->AsWeakPtr();
+ UtilityProcessHost::Create(
+ this,
+ BrowserThread::GetMessageLoopProxyForThread(thread_id))->AsWeakPtr();
utility_process_host_->DisableSandbox();
#if defined(OS_MACOSX)
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index c6dd5ad..3a47e65 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -10,6 +10,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/string_util.h"
+#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_restrictions.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
@@ -516,7 +517,6 @@ scoped_refptr<BrowserThemePack> BrowserThemePack::BuildFromDataPack(
}
bool BrowserThemePack::WriteToDisk(const FilePath& path) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
// Add resources for each of the property arrays.
RawDataForWriting resources;
resources[kHeaderID] = base::StringPiece(
@@ -1100,9 +1100,6 @@ void BrowserThemePack::CreateTabBackgroundImages(ImageCache* images) const {
void BrowserThemePack::RepackImages(const ImageCache& images,
RawImages* reencoded_images) const {
-
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
typedef std::vector<ui::ScaleFactor> ScaleFactors;
for (ImageCache::const_iterator it = images.begin();
it != images.end(); ++it) {
@@ -1150,7 +1147,6 @@ void BrowserThemePack::CopyImagesTo(const ImageCache& source,
void BrowserThemePack::AddRawImagesTo(const RawImages& images,
RawDataForWriting* out) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
for (RawImages::const_iterator it = images.begin(); it != images.end();
++it) {
(*out)[it->first] = base::StringPiece(
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc
index e1f660d..027315d 100644
--- a/chrome/browser/themes/theme_service.cc
+++ b/chrome/browser/themes/theme_service.cc
@@ -6,10 +6,12 @@
#include "base/bind.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/sequenced_task_runner.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/browser_theme_pack.h"
@@ -194,7 +196,8 @@ const int kToolbarButtonIDs[] = {
};
// Writes the theme pack to disk on a separate thread.
-void WritePackToDiskCallback(BrowserThemePack* pack, const FilePath& path) {
+void WritePackToDiskCallback(BrowserThemePack* pack,
+ const FilePath& path) {
if (!pack->WriteToDisk(path))
NOTREACHED() << "Could not write theme pack to disk";
}
@@ -682,10 +685,15 @@ void ThemeService::BuildFromExtension(const Extension* extension) {
return;
}
+ ExtensionService* service =
+ extensions::ExtensionSystem::Get(profile_)->extension_service();
+ if (!service)
+ return;
+
// Write the packed file to disk.
FilePath pack_path = extension->path().Append(chrome::kThemePackFilename);
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
+ service->GetFileTaskRunner()->PostTask(
+ FROM_HERE,
base::Bind(&WritePackToDiskCallback, pack, pack_path));
SavePackName(pack_path);
diff --git a/chrome/browser/web_resource/json_asynchronous_unpacker.cc b/chrome/browser/web_resource/json_asynchronous_unpacker.cc
index f797a2f..44dcbbc 100644
--- a/chrome/browser/web_resource/json_asynchronous_unpacker.cc
+++ b/chrome/browser/web_resource/json_asynchronous_unpacker.cc
@@ -105,7 +105,8 @@ class JSONAsynchronousUnpackerImpl
void StartProcessOnIOThread(BrowserThread::ID thread_id,
const std::string& json_data) {
- UtilityProcessHost* host = UtilityProcessHost::Create(this, thread_id);
+ UtilityProcessHost* host = UtilityProcessHost::Create(
+ this, BrowserThread::GetMessageLoopProxyForThread(thread_id));
host->EnableZygote();
// TODO(mrc): get proper file path when we start using web resources
// that need to be unpacked.