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) { |