| Index: chrome/browser/extensions/extensions_service.cc
|
| diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
|
| index 28ba10c966fe7d46da11c76fc5d526b7c705414e..6807f6ac5782a10b43b5c8380866aa7c8392f95a 100644
|
| --- a/chrome/browser/extensions/extensions_service.cc
|
| +++ b/chrome/browser/extensions/extensions_service.cc
|
| @@ -12,6 +12,7 @@
|
| #include "base/string_util.h"
|
| #include "base/time.h"
|
| #include "base/values.h"
|
| +#include "base/version.h"
|
| #include "chrome/browser/browser_process.h"
|
| #include "chrome/browser/chrome_thread.h"
|
| #include "chrome/browser/debugger/devtools_manager.h"
|
| @@ -97,6 +98,21 @@ static bool ShouldReloadExtensionManifest(const ExtensionInfo& info) {
|
|
|
| } // namespace
|
|
|
| +PendingExtensionInfo::PendingExtensionInfo(const GURL& update_url,
|
| + const Version& version,
|
| + bool is_theme,
|
| + bool install_silently)
|
| + : update_url(update_url),
|
| + version(version),
|
| + is_theme(is_theme),
|
| + install_silently(install_silently) {}
|
| +
|
| +PendingExtensionInfo::PendingExtensionInfo()
|
| + : update_url(),
|
| + version(),
|
| + is_theme(false),
|
| + install_silently(false) {}
|
| +
|
| // ExtensionsService.
|
|
|
| const char* ExtensionsService::kInstallDirectoryName = "Extensions";
|
| @@ -203,19 +219,41 @@ void ExtensionsService::InstallExtension(const FilePath& extension_path) {
|
| installer->InstallCrx(extension_path);
|
| }
|
|
|
| +namespace {
|
| + // TODO(akalin): Put this somewhere where both crx_installer.cc and
|
| + // this file can use it.
|
| + void DeleteFileHelper(const FilePath& path, bool recursive) {
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
|
| + file_util::Delete(path, recursive);
|
| + }
|
| +} // namespace
|
| +
|
| void ExtensionsService::UpdateExtension(const std::string& id,
|
| const FilePath& extension_path,
|
| const GURL& download_url) {
|
| - if (!GetExtensionByIdInternal(id, true, true)) {
|
| - LOG(WARNING) << "Will not update extension " << id << " because it is not "
|
| - << "installed";
|
| + PendingExtensionMap::const_iterator it = pending_extensions_.find(id);
|
| + if ((it == pending_extensions_.end()) &&
|
| + !GetExtensionByIdInternal(id, true, true)) {
|
| + LOG(WARNING) << "Will not update extension " << id
|
| + << " because it is not installed or pending";
|
| + // Delete extension_path since we're not creating a CrxInstaller
|
| + // that would do it for us.
|
| + ChromeThread::PostTask(
|
| + ChromeThread::FILE, FROM_HERE,
|
| + NewRunnableFunction(&DeleteFileHelper, extension_path, false));
|
| return;
|
| }
|
|
|
| + // We want a silent install only for non-pending extensions and
|
| + // pending extensions that have install_silently set.
|
| + ExtensionInstallUI* client =
|
| + ((it == pending_extensions_.end()) || it->second.install_silently) ?
|
| + NULL : new ExtensionInstallUI(profile_);
|
| +
|
| scoped_refptr<CrxInstaller> installer(
|
| new CrxInstaller(install_directory_,
|
| this, // frontend
|
| - NULL)); // no client (silent install)
|
| + client));
|
| installer->set_expected_id(id);
|
| installer->set_delete_source(true);
|
| installer->set_force_web_origin_to_download_url(true);
|
| @@ -223,6 +261,23 @@ void ExtensionsService::UpdateExtension(const std::string& id,
|
| installer->InstallCrx(extension_path);
|
| }
|
|
|
| +void ExtensionsService::AddPendingExtension(
|
| + const std::string& id, const GURL& update_url,
|
| + const Version& version, bool is_theme, bool install_silently) {
|
| + if (GetExtensionByIdInternal(id, true, true)) {
|
| + return;
|
| + }
|
| + AddPendingExtensionInternal(id, update_url, version,
|
| + is_theme, install_silently);
|
| +}
|
| +
|
| +void ExtensionsService::AddPendingExtensionInternal(
|
| + const std::string& id, const GURL& update_url,
|
| + const Version& version, bool is_theme, bool install_silently) {
|
| + pending_extensions_[id] =
|
| + PendingExtensionInfo(update_url, version, is_theme, install_silently);
|
| +}
|
| +
|
| void ExtensionsService::ReloadExtension(const std::string& extension_id) {
|
| FilePath path;
|
| Extension* current_extension = GetExtensionById(extension_id, false);
|
| @@ -823,6 +878,22 @@ void ExtensionsService::UpdateActiveExtensionsInCrashReporter() {
|
|
|
| void ExtensionsService::OnExtensionInstalled(Extension* extension,
|
| bool allow_privilege_increase) {
|
| + PendingExtensionMap::iterator it =
|
| + pending_extensions_.find(extension->id());
|
| + if (it != pending_extensions_.end() &&
|
| + (it->second.is_theme != extension->IsTheme())) {
|
| + LOG(WARNING) << "Not installing pending extension " << extension->id()
|
| + << " with is_theme = " << extension->IsTheme()
|
| + << "; expected is_theme = " << it->second.is_theme;
|
| + // Delete the extension directory since we're not going to load
|
| + // it.
|
| + ChromeThread::PostTask(
|
| + ChromeThread::FILE, FROM_HERE,
|
| + NewRunnableFunction(&DeleteFileHelper, extension->path(), true));
|
| + delete extension;
|
| + return;
|
| + }
|
| +
|
| extension_prefs_->OnExtensionInstalled(extension);
|
|
|
| // If the extension is a theme, tell the profile (and therefore ThemeProvider)
|
| @@ -841,6 +912,11 @@ void ExtensionsService::OnExtensionInstalled(Extension* extension,
|
|
|
| // Also load the extension.
|
| OnExtensionLoaded(extension, allow_privilege_increase);
|
| +
|
| + // Erase any pending extension.
|
| + if (it != pending_extensions_.end()) {
|
| + pending_extensions_.erase(it);
|
| + }
|
| }
|
|
|
| void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) {
|
|
|