// 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<ErrorList> 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<ExtensionError> 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<ExtensionError> error) {
EntryMap::iterator iter = map_.find(error->extension_id());
if (iter == map_.end()) {
iter = map_.insert(std::pair<std::string, ExtensionEntry*>(
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