| Index: chrome/browser/extensions/extension_service.cc
|
| diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
|
| index 33a608de54bc9bf81d58e6aa26c71ef1482ee662..4d7e99f0ee31ddc568cd3a3e95c24d99279024b6 100644
|
| --- a/chrome/browser/extensions/extension_service.cc
|
| +++ b/chrome/browser/extensions/extension_service.cc
|
| @@ -595,20 +595,33 @@ bool ExtensionService::UpdateExtension(const std::string& id,
|
| return true;
|
| }
|
|
|
| -void ExtensionService::ReloadExtension(const std::string extension_id) {
|
| +void ExtensionService::ReloadExtension(
|
| + // "transient" because the process of reloading may cause the reference
|
| + // to become invalid. Instead, use |extension_id|, a copy.
|
| + const std::string& transient_extension_id) {
|
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
|
|
| // If the extension is already reloading, don't reload again.
|
| - if (extension_prefs_->GetDisableReasons(extension_id) &
|
| + if (extension_prefs_->GetDisableReasons(transient_extension_id) &
|
| Extension::DISABLE_RELOAD) {
|
| return;
|
| }
|
|
|
| + // Ignore attempts to reload a blacklisted extension. Sometimes this can
|
| + // happen in a convoluted reload sequence triggered by the termination of a
|
| + // blacklisted extension and a naive attempt to reload it. For an example see
|
| + // http://crbug.com/373842.
|
| + if (registry_->blacklisted_extensions().Contains(transient_extension_id))
|
| + return;
|
| +
|
| base::FilePath path;
|
| - const Extension* current_extension = GetExtensionById(extension_id, false);
|
| +
|
| + std::string extension_id = transient_extension_id;
|
| + const Extension* transient_current_extension =
|
| + GetExtensionById(extension_id, false);
|
|
|
| // Disable the extension if it's loaded. It might not be loaded if it crashed.
|
| - if (current_extension) {
|
| + if (transient_current_extension) {
|
| // If the extension has an inspector open for its background page, detach
|
| // the inspector and hang onto a cookie for it, so that we can reattach
|
| // later.
|
| @@ -624,15 +637,18 @@ void ExtensionService::ReloadExtension(const std::string extension_id) {
|
| orphaned_dev_tools_[extension_id] = agent_host;
|
| }
|
|
|
| - path = current_extension->path();
|
| + path = transient_current_extension->path();
|
| // BeingUpgraded is set back to false when the extension is added.
|
| - system_->runtime_data()->SetBeingUpgraded(current_extension, true);
|
| + system_->runtime_data()->SetBeingUpgraded(transient_current_extension,
|
| + true);
|
| DisableExtension(extension_id, Extension::DISABLE_RELOAD);
|
| reloading_extensions_.insert(extension_id);
|
| } else {
|
| path = unloaded_extension_paths_[extension_id];
|
| }
|
|
|
| + transient_current_extension = NULL;
|
| +
|
| if (delayed_installs_.Contains(extension_id)) {
|
| FinishDelayedInstallation(extension_id);
|
| return;
|
| @@ -666,12 +682,16 @@ void ExtensionService::ReloadExtension(const std::string extension_id) {
|
| SetBeingReloaded(extension_id, false);
|
| }
|
|
|
| -bool ExtensionService::UninstallExtension(const std::string& extension_id,
|
| - bool external_uninstall,
|
| - base::string16* error) {
|
| +bool ExtensionService::UninstallExtension(
|
| + // "transient" because the process of uninstalling may cause the reference
|
| + // to become invalid. Instead, use |extenson->id()|.
|
| + const std::string& transient_extension_id,
|
| + bool external_uninstall,
|
| + base::string16* error) {
|
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
|
|
| - scoped_refptr<const Extension> extension(GetInstalledExtension(extension_id));
|
| + scoped_refptr<const Extension> extension =
|
| + GetInstalledExtension(transient_extension_id);
|
|
|
| // Callers should not send us nonexistent extensions.
|
| CHECK(extension.get());
|
| @@ -724,7 +744,7 @@ bool ExtensionService::UninstallExtension(const std::string& extension_id,
|
|
|
| // Unload before doing more cleanup to ensure that nothing is hanging on to
|
| // any of these resources.
|
| - UnloadExtension(extension_id, UnloadedExtensionInfo::REASON_UNINSTALL);
|
| + UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UNINSTALL);
|
|
|
| // Tell the backend to start deleting installed extensions on the file thread.
|
| if (!Manifest::IsUnpackedLocation(extension->location())) {
|
| @@ -732,16 +752,16 @@ bool ExtensionService::UninstallExtension(const std::string& extension_id,
|
| FROM_HERE,
|
| base::Bind(&extensions::file_util::UninstallExtension,
|
| install_directory_,
|
| - extension_id)))
|
| + extension->id())))
|
| NOTREACHED();
|
| }
|
|
|
| // Do not remove the data of ephemeral apps. They will be garbage collected by
|
| // EphemeralAppService.
|
| - if (!extension_prefs_->IsEphemeralApp(extension_id))
|
| + if (!extension_prefs_->IsEphemeralApp(extension->id()))
|
| extensions::DataDeleter::StartDeleting(profile_, extension.get());
|
|
|
| - UntrackTerminatedExtension(extension_id);
|
| + UntrackTerminatedExtension(extension->id());
|
|
|
| // Notify interested parties that we've uninstalled this extension.
|
| content::NotificationService::current()->Notify(
|
| @@ -750,14 +770,14 @@ bool ExtensionService::UninstallExtension(const std::string& extension_id,
|
| content::Details<const Extension>(extension.get()));
|
|
|
| if (extension_sync_service_) {
|
| - extension_sync_service_->ProcessSyncUninstallExtension(extension_id,
|
| + extension_sync_service_->ProcessSyncUninstallExtension(extension->id(),
|
| sync_change);
|
| }
|
|
|
| - delayed_installs_.Remove(extension_id);
|
| + delayed_installs_.Remove(extension->id());
|
|
|
| - extension_prefs_->OnExtensionUninstalled(extension_id, extension->location(),
|
| - external_uninstall);
|
| + extension_prefs_->OnExtensionUninstalled(
|
| + extension->id(), extension->location(), external_uninstall);
|
|
|
| // Track the uninstallation.
|
| UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2);
|
|
|