error_console.cc revision ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/extensions/error_console/error_console.h" 6 7#include <list> 8 9#include "base/lazy_instance.h" 10#include "base/stl_util.h" 11#include "chrome/browser/chrome_notification_types.h" 12#include "chrome/browser/extensions/extension_system.h" 13#include "chrome/browser/profiles/profile.h" 14#include "chrome/common/extensions/extension.h" 15#include "content/public/browser/notification_details.h" 16#include "content/public/browser/notification_service.h" 17#include "content/public/browser/notification_source.h" 18#include "extensions/common/constants.h" 19 20namespace extensions { 21 22namespace { 23 24const size_t kMaxErrorsPerExtension = 100; 25 26// Iterate through an error list and remove and delete all errors which were 27// from an incognito context. 28void DeleteIncognitoErrorsFromList(ErrorConsole::ErrorList* list) { 29 ErrorConsole::ErrorList::iterator iter = list->begin(); 30 while (iter != list->end()) { 31 if ((*iter)->from_incognito()) { 32 delete *iter; 33 iter = list->erase(iter); 34 } else { 35 ++iter; 36 } 37 } 38} 39 40base::LazyInstance<ErrorConsole::ErrorList> g_empty_error_list = 41 LAZY_INSTANCE_INITIALIZER; 42 43} // namespace 44 45void ErrorConsole::Observer::OnErrorConsoleDestroyed() { 46} 47 48ErrorConsole::ErrorConsole(Profile* profile) : profile_(profile) { 49 registrar_.Add(this, 50 chrome::NOTIFICATION_PROFILE_DESTROYED, 51 content::NotificationService::AllBrowserContextsAndSources()); 52 registrar_.Add(this, 53 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 54 content::Source<Profile>(profile_)); 55} 56 57ErrorConsole::~ErrorConsole() { 58 FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed()); 59 RemoveAllErrors(); 60} 61 62// static 63ErrorConsole* ErrorConsole::Get(Profile* profile) { 64 return ExtensionSystem::Get(profile)->error_console(); 65} 66 67void ErrorConsole::ReportError(scoped_ptr<const ExtensionError> scoped_error) { 68 DCHECK(thread_checker_.CalledOnValidThread()); 69 70 const ExtensionError* error = scoped_error.release(); 71 // If there are too many errors for an extension already, limit ourselves to 72 // the most recent ones. 73 ErrorList* error_list = &errors_[error->extension_id()]; 74 if (error_list->size() >= kMaxErrorsPerExtension) { 75 delete error_list->front(); 76 error_list->pop_front(); 77 } 78 error_list->push_back(error); 79 80 FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(error)); 81} 82 83const ErrorConsole::ErrorList& ErrorConsole::GetErrorsForExtension( 84 const std::string& extension_id) const { 85 ErrorMap::const_iterator iter = errors_.find(extension_id); 86 if (iter != errors_.end()) 87 return iter->second; 88 return g_empty_error_list.Get(); 89} 90 91void ErrorConsole::AddObserver(Observer* observer) { 92 DCHECK(thread_checker_.CalledOnValidThread()); 93 observers_.AddObserver(observer); 94} 95 96void ErrorConsole::RemoveObserver(Observer* observer) { 97 DCHECK(thread_checker_.CalledOnValidThread()); 98 observers_.RemoveObserver(observer); 99} 100 101void ErrorConsole::RemoveIncognitoErrors() { 102 for (ErrorMap::iterator iter = errors_.begin(); 103 iter != errors_.end(); ++iter) { 104 DeleteIncognitoErrorsFromList(&(iter->second)); 105 } 106} 107 108void ErrorConsole::RemoveErrorsForExtension(const std::string& extension_id) { 109 ErrorMap::iterator iter = errors_.find(extension_id); 110 if (iter != errors_.end()) { 111 STLDeleteContainerPointers(iter->second.begin(), iter->second.end()); 112 errors_.erase(iter); 113 } 114} 115 116void ErrorConsole::RemoveAllErrors() { 117 for (ErrorMap::iterator iter = errors_.begin(); iter != errors_.end(); ++iter) 118 STLDeleteContainerPointers(iter->second.begin(), iter->second.end()); 119 errors_.clear(); 120} 121 122void ErrorConsole::Observe(int type, 123 const content::NotificationSource& source, 124 const content::NotificationDetails& details) { 125 switch (type) { 126 case chrome::NOTIFICATION_PROFILE_DESTROYED: { 127 Profile* profile = content::Source<Profile>(source).ptr(); 128 // If incognito profile which we are associated with is destroyed, also 129 // destroy all incognito errors. 130 if (profile->IsOffTheRecord() && profile_->IsSameProfile(profile)) 131 RemoveIncognitoErrors(); 132 break; 133 } 134 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: 135 // No need to check the profile here, since we registered to only receive 136 // notifications from our own. 137 RemoveErrorsForExtension( 138 content::Details<Extension>(details).ptr()->id()); 139 break; 140 default: 141 NOTREACHED(); 142 } 143} 144 145} // namespace extensions 146