Chromium Code Reviews| Index: chrome/browser/extensions/extension_service.cc |
| diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc |
| index f924d0ae1e3573e39803dc584a20a2fe72be3422..10ae3ec15b208d939e0f9e25576390e83689dab1 100644 |
| --- a/chrome/browser/extensions/extension_service.cc |
| +++ b/chrome/browser/extensions/extension_service.cc |
| @@ -70,7 +70,6 @@ |
| #include "extensions/browser/app_sorting.h" |
| #include "extensions/browser/event_router.h" |
| #include "extensions/browser/extension_host.h" |
| -#include "extensions/browser/extension_prefs.h" |
| #include "extensions/browser/extension_registry.h" |
| #include "extensions/browser/extension_system.h" |
| #include "extensions/browser/extensions_browser_client.h" |
| @@ -1770,55 +1769,38 @@ void ExtensionService::OnExtensionInstalled( |
| else |
| extension_prefs_->SetExtensionDisabled(id, disable_reasons); |
| - if (ShouldDelayExtensionUpdate( |
| - id, |
| - !!(install_flags & extensions::kInstallFlagInstallImmediately))) { |
| - extension_prefs_->SetDelayedInstallInfo( |
| - extension, |
| - initial_state, |
| - install_flags, |
| - extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, |
| - page_ordinal, |
| - install_parameter); |
| - |
| - // Transfer ownership of |extension|. |
| - delayed_installs_.Insert(extension); |
| - |
| - // Notify observers that app update is available. |
| - FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, |
| - OnAppUpdateAvailable(extension)); |
| - return; |
| - } |
| + extensions::ExtensionPrefs::DelayReason delay_reason; |
| + extensions::InstallDelayer::Action action = GetDelayedInstallAction( |
| + extension, !!(install_flags & extensions::kInstallFlagInstallImmediately), |
| + &delay_reason); |
| + switch (action) { |
| + case extensions::InstallDelayer::INSTALL: |
| + AddNewOrUpdatedExtension(extension, initial_state, install_flags, |
| + page_ordinal, install_parameter); |
| + return; |
| + case extensions::InstallDelayer::DELAY: |
| + extension_prefs_->SetDelayedInstallInfo(extension, initial_state, |
| + install_flags, delay_reason, |
| + page_ordinal, install_parameter); |
| - extensions::SharedModuleService::ImportStatus status = |
| - shared_module_service_->SatisfyImports(extension); |
| - if (installs_delayed_for_gc_) { |
| - extension_prefs_->SetDelayedInstallInfo( |
| - extension, |
| - initial_state, |
| - install_flags, |
| - extensions::ExtensionPrefs::DELAY_REASON_GC, |
| - page_ordinal, |
| - install_parameter); |
| - delayed_installs_.Insert(extension); |
| - } else if (status != SharedModuleService::IMPORT_STATUS_OK) { |
| - if (status == SharedModuleService::IMPORT_STATUS_UNSATISFIED) { |
| - extension_prefs_->SetDelayedInstallInfo( |
| - extension, |
| - initial_state, |
| - install_flags, |
| - extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS, |
| - page_ordinal, |
| - install_parameter); |
| + // Transfer ownership of |extension|. |
| delayed_installs_.Insert(extension); |
| - } |
| - } else { |
| - AddNewOrUpdatedExtension(extension, |
| - initial_state, |
| - install_flags, |
| - page_ordinal, |
| - install_parameter); |
| + |
| + if (delay_reason == |
| + extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE) { |
| + // Notify observers that app update is available. |
| + FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_, |
| + OnAppUpdateAvailable(extension)); |
| + } |
| + return; |
| + case extensions::InstallDelayer::ABORT: |
| + // Do nothing to abort the install. One such case is the shared module |
| + // service gets IMPORT_STATUS_UNRECOVERABLE status for the pending |
| + // install. |
| + return; |
| } |
| + |
| + NOTREACHED() << "Unknown action for delayed install: " << action; |
| } |
| void ExtensionService::OnExtensionManagementSettingsChanged() { |
| @@ -1869,33 +1851,26 @@ void ExtensionService::AddNewOrUpdatedExtension( |
| void ExtensionService::MaybeFinishDelayedInstallation( |
| const std::string& extension_id) { |
| // Check if the extension already got installed. |
| - if (!delayed_installs_.Contains(extension_id)) |
| - return; |
| - extensions::ExtensionPrefs::DelayReason reason = |
| - extension_prefs_->GetDelayedInstallReason(extension_id); |
| - |
| - // Check if the extension is idle. DELAY_REASON_NONE is used for older |
| - // preferences files that will not have set this field but it was previously |
| - // only used for idle updates. |
| - if ((reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE || |
| - reason == extensions::ExtensionPrefs::DELAY_REASON_NONE) && |
|
xiyuan
2016/04/15 20:04:23
Note the changed behavior here. Before the CL, the
|
| - is_ready() && !extensions::util::IsExtensionIdle(extension_id, profile_)) |
| + const Extension* extension = delayed_installs_.GetByID(extension_id); |
| + if (!extension) |
| return; |
| - const Extension* extension = delayed_installs_.GetByID(extension_id); |
| - if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS) { |
| - extensions::SharedModuleService::ImportStatus status = |
| - shared_module_service_->SatisfyImports(extension); |
| - if (status != SharedModuleService::IMPORT_STATUS_OK) { |
| - if (status == SharedModuleService::IMPORT_STATUS_UNRECOVERABLE) { |
| - delayed_installs_.Remove(extension_id); |
| - // Make sure no version of the extension is actually installed, (i.e., |
| - // that this delayed install was not an update). |
| - CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get()); |
| - extension_prefs_->DeleteExtensionPrefs(extension_id); |
| - } |
| + extensions::ExtensionPrefs::DelayReason reason; |
| + const extensions::InstallDelayer::Action action = GetDelayedInstallAction( |
| + extension, false /* install_immediately*/, &reason); |
| + switch (action) { |
| + case extensions::InstallDelayer::INSTALL: |
| + break; |
| + case extensions::InstallDelayer::DELAY: |
| + // Bail out and continue to delay the install. |
| + return; |
| + case extensions::InstallDelayer::ABORT: |
| + delayed_installs_.Remove(extension_id); |
| + // Make sure no version of the extension is actually installed, (i.e., |
| + // that this delayed install was not an update). |
| + CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get()); |
| + extension_prefs_->DeleteExtensionPrefs(extension_id); |
| return; |
| - } |
| } |
| FinishDelayedInstallation(extension_id); |
| @@ -2246,41 +2221,21 @@ bool ExtensionService::CanBlockExtension(const Extension* extension) const { |
| !system_->management_policy()->MustRemainEnabled(extension, nullptr); |
| } |
| -bool ExtensionService::ShouldDelayExtensionUpdate( |
| - const std::string& extension_id, |
| - bool install_immediately) const { |
| - const char kOnUpdateAvailableEvent[] = "runtime.onUpdateAvailable"; |
| - |
| - // If delayed updates are globally disabled, or just for this extension, |
| - // don't delay. |
| - if (!install_updates_when_idle_ || install_immediately) |
| - return false; |
| - |
| - const Extension* old = GetInstalledExtension(extension_id); |
| - // If there is no old extension, this is not an update, so don't delay. |
| - if (!old) |
| - return false; |
| - |
| - if (extensions::BackgroundInfo::HasPersistentBackgroundPage(old)) { |
| - // Delay installation if the extension listens for the onUpdateAvailable |
| - // event. |
| - return extensions::EventRouter::Get(profile_) |
| - ->ExtensionHasEventListener(extension_id, kOnUpdateAvailableEvent); |
| - } else { |
| - // Delay installation if the extension is not idle. |
| - return !extensions::util::IsExtensionIdle(extension_id, profile_); |
| +extensions::InstallDelayer::Action ExtensionService::GetDelayedInstallAction( |
| + const extensions::Extension* extension, |
| + bool install_immediately, |
| + extensions::ExtensionPrefs::DelayReason* reason) const { |
| + for (const auto& entry : install_delayer_registry_) { |
| + extensions::InstallDelayer* const delayer = entry.second; |
| + extensions::InstallDelayer::Action action = |
| + delayer->GetDelayedInstallAction(extension, install_immediately); |
| + if (action != extensions::InstallDelayer::INSTALL) { |
| + *reason = entry.first; |
| + return action; |
| + } |
| } |
| -} |
| -void ExtensionService::OnGarbageCollectIsolatedStorageStart() { |
| - DCHECK(!installs_delayed_for_gc_); |
| - installs_delayed_for_gc_ = true; |
| -} |
| - |
| -void ExtensionService::OnGarbageCollectIsolatedStorageFinished() { |
| - DCHECK(installs_delayed_for_gc_); |
| - installs_delayed_for_gc_ = false; |
| - MaybeFinishDelayedInstallations(); |
| + return extensions::InstallDelayer::INSTALL; |
| } |
| void ExtensionService::MaybeFinishDelayedInstallations() { |
| @@ -2438,6 +2393,25 @@ void ExtensionService::RemoveUpdateObserver( |
| update_observers_.RemoveObserver(observer); |
| } |
| +void ExtensionService::RegisterInstallDelayer( |
| + extensions::ExtensionPrefs::DelayReason reason, |
| + extensions::InstallDelayer* install_delayer) { |
| + DCHECK(install_delayer_registry_.end() == |
| + install_delayer_registry_.find(reason)); |
| + install_delayer_registry_[reason] = install_delayer; |
| +} |
| + |
| +void ExtensionService::UnregisterInstallDelayer( |
| + extensions::InstallDelayer* install_delayer) { |
| + for (auto it = install_delayer_registry_.begin(); |
| + it != install_delayer_registry_.end(); ++it) { |
| + if (it->second == install_delayer) { |
| + install_delayer_registry_.erase(it); |
| + return; |
| + } |
| + } |
| +} |
| + |
| // Used only by test code. |
| void ExtensionService::UnloadAllExtensionsInternal() { |
| profile_->GetExtensionSpecialStoragePolicy()->RevokeRightsForAllExtensions(); |