| Index: chrome/browser/background/background_contents_service.cc
|
| diff --git a/chrome/browser/background/background_contents_service.cc b/chrome/browser/background/background_contents_service.cc
|
| index 52d401d5ecf1f37403302fe11cb02a187c7b7067..1131f422f6a25cb15352b89a2e0636bd5eecb6a6 100644
|
| --- a/chrome/browser/background/background_contents_service.cc
|
| +++ b/chrome/browser/background/background_contents_service.cc
|
| @@ -280,7 +280,9 @@ int BackgroundContentsService::restart_delay_in_ms_ = 3000; // 3 seconds.
|
| BackgroundContentsService::BackgroundContentsService(
|
| Profile* profile,
|
| const base::CommandLine* command_line)
|
| - : prefs_(NULL), extension_registry_observer_(this) {
|
| + : prefs_(NULL),
|
| + extension_registry_observer_(this),
|
| + weak_ptr_factory_(this) {
|
| // Don't load/store preferences if the parent profile is incognito.
|
| if (!profile->IsOffTheRecord())
|
| prefs_ = profile->GetPrefs();
|
| @@ -478,6 +480,23 @@ void BackgroundContentsService::OnExtensionLoaded(
|
| }
|
| }
|
|
|
| + // If there is an existing BackoffEntry for the extension, clear it if
|
| + // the component extension stays loaded for 60 seconds. This avoids the
|
| + // situation of effectively disabling an extension for the entire browser
|
| + // session if there was a periodic crash (sometimes caused by another source).
|
| + if (extensions::Manifest::IsComponentLocation(extension->location())) {
|
| + ComponentExtensionBackoffEntryMap::const_iterator it =
|
| + component_backoff_map_.find(extension->id());
|
| + if (it != component_backoff_map_.end()) {
|
| + net::BackoffEntry* entry = component_backoff_map_[extension->id()].get();
|
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE,
|
| + base::Bind(&BackgroundContentsService::MaybeClearBackoffEntry,
|
| + weak_ptr_factory_.GetWeakPtr(), extension->id(),
|
| + entry->failure_count()),
|
| + base::TimeDelta::FromSeconds(60));
|
| + }
|
| + }
|
| +
|
| // Close the crash notification balloon for the app/extension, if any.
|
| ScheduleCloseBalloon(extension->id(), profile);
|
| SendChangeNotification(profile);
|
| @@ -540,21 +559,21 @@ void BackgroundContentsService::RestartForceInstalledExtensionOnCrash(
|
| // If the extension was a component extension, use exponential backoff when
|
| // attempting to reload.
|
| if (extensions::Manifest::IsComponentLocation(extension->location())) {
|
| - ExtensionBackoffEntryMap::const_iterator it =
|
| - backoff_map_.find(extension->id());
|
| + ComponentExtensionBackoffEntryMap::const_iterator it =
|
| + component_backoff_map_.find(extension->id());
|
|
|
| // Create a BackoffEntry if this is the first time we try to reload this
|
| // particular extension.
|
| - if (it == backoff_map_.end()) {
|
| + if (it == component_backoff_map_.end()) {
|
| std::unique_ptr<net::BackoffEntry> backoff_entry(
|
| new net::BackoffEntry(&kExtensionReloadBackoffPolicy));
|
| - backoff_map_.insert(
|
| + component_backoff_map_.insert(
|
| std::pair<extensions::ExtensionId,
|
| std::unique_ptr<net::BackoffEntry>>(
|
| extension->id(), std::move(backoff_entry)));
|
| }
|
|
|
| - net::BackoffEntry* entry = backoff_map_[extension->id()].get();
|
| + net::BackoffEntry* entry = component_backoff_map_[extension->id()].get();
|
| entry->InformOfRequest(false);
|
| restart_delay = entry->GetTimeUntilRelease().InMilliseconds();
|
| }
|
| @@ -604,6 +623,22 @@ void BackgroundContentsService::SendChangeNotification(Profile* profile) {
|
| content::Details<BackgroundContentsService>(this));
|
| }
|
|
|
| +void BackgroundContentsService::MaybeClearBackoffEntry(
|
| + const std::string extension_id,
|
| + int expected_failure_count) {
|
| + ComponentExtensionBackoffEntryMap::const_iterator it =
|
| + component_backoff_map_.find(extension_id);
|
| + if (it == component_backoff_map_.end())
|
| + return;
|
| +
|
| + net::BackoffEntry* entry = component_backoff_map_[extension_id].get();
|
| +
|
| + // Only remove the BackoffEntry if there has has been no failure for
|
| + // |extension_id| since loading.
|
| + if (entry->failure_count() == expected_failure_count)
|
| + component_backoff_map_.erase(it);
|
| +}
|
| +
|
| void BackgroundContentsService::LoadBackgroundContentsForExtension(
|
| Profile* profile,
|
| const std::string& extension_id) {
|
|
|