Chromium Code Reviews| 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..c15780f17863a7069de55871eacbcaaa9adc2b2b 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::FromMilliseconds(60000 /* 60 seconds */)); |
|
Wez
2016/09/03 06:48:34
nit: Just use FromSeconds directly?
apacible
2016/09/05 00:34:37
Done.
|
| + } |
| + } |
| + |
| // 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) { |