// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "extensions/browser/error_map.h" #include "base/lazy_instance.h" #include "base/stl_util.h" #include "extensions/common/extension.h" namespace extensions { namespace { // The maximum number of errors to be stored per extension. const size_t kMaxErrorsPerExtension = 100; base::LazyInstance g_empty_error_list = LAZY_INSTANCE_INITIALIZER; } // namespace //////////////////////////////////////////////////////////////////////////////// // ErrorMap::ExtensionEntry ErrorMap::ExtensionEntry::ExtensionEntry() { } ErrorMap::ExtensionEntry::~ExtensionEntry() { DeleteAllErrors(); } void ErrorMap::ExtensionEntry::DeleteAllErrors() { STLDeleteContainerPointers(list_.begin(), list_.end()); list_.clear(); } void ErrorMap::ExtensionEntry::DeleteIncognitoErrors() { ErrorList::iterator iter = list_.begin(); while (iter != list_.end()) { if ((*iter)->from_incognito()) { delete *iter; iter = list_.erase(iter); } else { ++iter; } } } void ErrorMap::ExtensionEntry::DeleteErrorsOfType(ExtensionError::Type type) { ErrorList::iterator iter = list_.begin(); while (iter != list_.end()) { if ((*iter)->type() == type) { delete *iter; iter = list_.erase(iter); } else { ++iter; } } } const ExtensionError* ErrorMap::ExtensionEntry::AddError( scoped_ptr error) { for (ErrorList::iterator iter = list_.begin(); iter != list_.end(); ++iter) { // If we find a duplicate error, remove the old error and add the new one, // incrementing the occurrence count of the error. We use the new error // for runtime errors, so we can link to the latest context, inspectable // view, etc. if (error->IsEqual(*iter)) { error->set_occurrences((*iter)->occurrences() + 1); delete *iter; list_.erase(iter); break; } } // If there are too many errors for an extension already, limit ourselves to // the most recent ones. if (list_.size() >= kMaxErrorsPerExtension) { delete list_.front(); list_.pop_front(); } list_.push_back(error.release()); return list_.back(); } //////////////////////////////////////////////////////////////////////////////// // ErrorMap ErrorMap::ErrorMap() { } ErrorMap::~ErrorMap() { RemoveAllErrors(); } const ErrorList& ErrorMap::GetErrorsForExtension( const std::string& extension_id) const { EntryMap::const_iterator iter = map_.find(extension_id); return iter != map_.end() ? *iter->second->list() : g_empty_error_list.Get(); } const ExtensionError* ErrorMap::AddError(scoped_ptr error) { EntryMap::iterator iter = map_.find(error->extension_id()); if (iter == map_.end()) { iter = map_.insert(std::pair( error->extension_id(), new ExtensionEntry)).first; } return iter->second->AddError(error.Pass()); } void ErrorMap::Remove(const std::string& extension_id) { EntryMap::iterator iter = map_.find(extension_id); if (iter == map_.end()) return; delete iter->second; map_.erase(iter); } void ErrorMap::RemoveErrorsForExtensionOfType(const std::string& extension_id, ExtensionError::Type type) { EntryMap::iterator iter = map_.find(extension_id); if (iter != map_.end()) iter->second->DeleteErrorsOfType(type); } void ErrorMap::RemoveIncognitoErrors() { for (EntryMap::iterator iter = map_.begin(); iter != map_.end(); ++iter) iter->second->DeleteIncognitoErrors(); } void ErrorMap::RemoveAllErrors() { for (EntryMap::iterator iter = map_.begin(); iter != map_.end(); ++iter) { iter->second->DeleteAllErrors(); delete iter->second; } map_.clear(); } } // namespace extensions