Chromium Code Reviews| Index: chrome/browser/extensions/error_console/error_console.cc |
| diff --git a/chrome/browser/extensions/error_console/error_console.cc b/chrome/browser/extensions/error_console/error_console.cc |
| index 94eedd8274257b8b3e8ba1ca2e6b67e9576e169c..cff063cd3adc45272e927bd7140317f31fcc40c1 100644 |
| --- a/chrome/browser/extensions/error_console/error_console.cc |
| +++ b/chrome/browser/extensions/error_console/error_console.cc |
| @@ -4,12 +4,14 @@ |
| #include "chrome/browser/extensions/error_console/error_console.h" |
| -#include <algorithm> |
| +#include <list> |
| +#include "base/lazy_instance.h" |
| +#include "base/stl_util.h" |
| #include "chrome/browser/chrome_notification_types.h" |
| -#include "chrome/browser/extensions/error_console/extension_error.h" |
| #include "chrome/browser/extensions/extension_system.h" |
| #include "chrome/browser/profiles/profile.h" |
| +#include "chrome/common/extensions/extension.h" |
| #include "content/public/browser/notification_details.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/notification_source.h" |
| @@ -17,6 +19,29 @@ |
| namespace extensions { |
| +namespace { |
| + |
| +const size_t kMaxErrorsPerExtension = 100; |
| + |
| +// Iterate through an error list and remove and delete all errors which were |
| +// from an incognito context. |
| +void DeleteIncognitoErrorsFromList(ErrorConsole::ErrorList* list) { |
| + ErrorConsole::ErrorList::iterator iter = list->begin(); |
| + while (iter != list->end()) { |
| + if ((*iter)->from_incognito()) { |
| + delete *iter; |
|
Devlin
2013/08/08 23:24:13
Forgot to delete *iter here.
|
| + iter = list->erase(iter); |
| + } else { |
| + ++iter; |
| + } |
| + } |
| +} |
| + |
| +base::LazyInstance<ErrorConsole::ErrorList> g_empty_error_list = |
| + LAZY_INSTANCE_INITIALIZER; |
| + |
| +} // namespace |
| + |
| void ErrorConsole::Observer::OnErrorConsoleDestroyed() { |
| } |
| @@ -24,10 +49,14 @@ ErrorConsole::ErrorConsole(Profile* profile) : profile_(profile) { |
| registrar_.Add(this, |
| chrome::NOTIFICATION_PROFILE_DESTROYED, |
| content::NotificationService::AllBrowserContextsAndSources()); |
| + registrar_.Add(this, |
| + chrome::NOTIFICATION_EXTENSION_UNINSTALLED, |
| + content::Source<Profile>(profile_)); |
| } |
| ErrorConsole::~ErrorConsole() { |
| FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed()); |
| + RemoveAllErrors(); |
| } |
| // static |
| @@ -35,31 +64,28 @@ ErrorConsole* ErrorConsole::Get(Profile* profile) { |
| return ExtensionSystem::Get(profile)->error_console(); |
| } |
| -void ErrorConsole::ReportError(scoped_ptr<ExtensionError> error) { |
| +void ErrorConsole::ReportError(scoped_ptr<const ExtensionError> scoped_error) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| - errors_.push_back(error.release()); |
| - FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(errors_.back())); |
| -} |
| -ErrorConsole::WeakErrorList ErrorConsole::GetErrorsForExtension( |
| - const std::string& extension_id) const { |
| - WeakErrorList result; |
| - for (ErrorList::const_iterator iter = errors_.begin(); |
| - iter != errors_.end(); ++iter) { |
| - if ((*iter)->extension_id() == extension_id) |
| - result.push_back(*iter); |
| + const ExtensionError* error = scoped_error.release(); |
| + // If there are too many errors for an extension already, limit ourselves to |
| + // the most recent ones. |
| + ErrorList* error_list = &errors_[error->extension_id()]; |
| + if (error_list->size() >= kMaxErrorsPerExtension) { |
| + delete error_list->front(); |
| + error_list->pop_front(); |
| } |
| - return result; |
| -} |
| + error_list->push_back(error); |
| -void ErrorConsole::RemoveError(const ExtensionError* error) { |
| - ErrorList::iterator iter = std::find(errors_.begin(), errors_.end(), error); |
| - CHECK(iter != errors_.end()); |
| - errors_.erase(iter); |
| + FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(error)); |
| } |
| -void ErrorConsole::RemoveAllErrors() { |
| - errors_.clear(); |
| +const ErrorConsole::ErrorList& ErrorConsole::GetErrorsForExtension( |
| + const std::string& extension_id) const { |
| + ErrorMap::const_iterator iter = errors_.find(extension_id); |
| + if (iter != errors_.end()) |
| + return iter->second; |
| + return g_empty_error_list.Get(); |
| } |
| void ErrorConsole::AddObserver(Observer* observer) { |
| @@ -73,19 +99,26 @@ void ErrorConsole::RemoveObserver(Observer* observer) { |
| } |
| void ErrorConsole::RemoveIncognitoErrors() { |
| - WeakErrorList to_remove; |
| - for (ErrorList::const_iterator iter = errors_.begin(); |
| + for (ErrorMap::iterator iter = errors_.begin(); |
| iter != errors_.end(); ++iter) { |
| - if ((*iter)->from_incognito()) |
| - to_remove.push_back(*iter); |
| + DeleteIncognitoErrorsFromList(&(iter->second)); |
| } |
| +} |
| - for (WeakErrorList::const_iterator iter = to_remove.begin(); |
| - iter != to_remove.end(); ++iter) { |
| - RemoveError(*iter); |
| +void ErrorConsole::RemoveErrorsForExtension(const std::string& extension_id) { |
| + ErrorMap::iterator iter = errors_.find(extension_id); |
| + if (iter != errors_.end()) { |
| + STLDeleteContainerPointers(iter->second.begin(), iter->second.end()); |
| + errors_.erase(iter); |
| } |
| } |
| +void ErrorConsole::RemoveAllErrors() { |
| + for (ErrorMap::iterator iter = errors_.begin(); iter != errors_.end(); ++iter) |
| + STLDeleteContainerPointers(iter->second.begin(), iter->second.end()); |
| + errors_.clear(); |
| +} |
| + |
| void ErrorConsole::Observe(int type, |
| const content::NotificationSource& source, |
| const content::NotificationDetails& details) { |
| @@ -98,6 +131,12 @@ void ErrorConsole::Observe(int type, |
| RemoveIncognitoErrors(); |
| break; |
| } |
| + case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: |
| + // No need to check the profile here, since we registered to only receive |
| + // notifications from our own. |
| + RemoveErrorsForExtension( |
| + content::Details<Extension>(details).ptr()->id()); |
| + break; |
| default: |
| NOTREACHED(); |
| } |