1// Copyright 2014 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 "extensions/browser/error_map.h"
6
7#include "base/lazy_instance.h"
8#include "base/stl_util.h"
9#include "extensions/common/extension.h"
10
11namespace extensions {
12namespace {
13
14// The maximum number of errors to be stored per extension.
15const size_t kMaxErrorsPerExtension = 100;
16
17base::LazyInstance<ErrorList> g_empty_error_list = LAZY_INSTANCE_INITIALIZER;
18
19}  // namespace
20
21////////////////////////////////////////////////////////////////////////////////
22// ErrorMap::ExtensionEntry
23ErrorMap::ExtensionEntry::ExtensionEntry() {
24}
25
26ErrorMap::ExtensionEntry::~ExtensionEntry() {
27  DeleteAllErrors();
28}
29
30void ErrorMap::ExtensionEntry::DeleteAllErrors() {
31  STLDeleteContainerPointers(list_.begin(), list_.end());
32  list_.clear();
33}
34
35void ErrorMap::ExtensionEntry::DeleteIncognitoErrors() {
36  ErrorList::iterator iter = list_.begin();
37  while (iter != list_.end()) {
38    if ((*iter)->from_incognito()) {
39      delete *iter;
40      iter = list_.erase(iter);
41    } else {
42      ++iter;
43    }
44  }
45}
46
47void ErrorMap::ExtensionEntry::DeleteErrorsOfType(ExtensionError::Type type) {
48  ErrorList::iterator iter = list_.begin();
49  while (iter != list_.end()) {
50    if ((*iter)->type() == type) {
51      delete *iter;
52      iter = list_.erase(iter);
53    } else {
54      ++iter;
55    }
56  }
57}
58
59const ExtensionError* ErrorMap::ExtensionEntry::AddError(
60    scoped_ptr<ExtensionError> error) {
61  for (ErrorList::iterator iter = list_.begin(); iter != list_.end(); ++iter) {
62    // If we find a duplicate error, remove the old error and add the new one,
63    // incrementing the occurrence count of the error. We use the new error
64    // for runtime errors, so we can link to the latest context, inspectable
65    // view, etc.
66    if (error->IsEqual(*iter)) {
67      error->set_occurrences((*iter)->occurrences() + 1);
68      delete *iter;
69      list_.erase(iter);
70      break;
71    }
72  }
73
74  // If there are too many errors for an extension already, limit ourselves to
75  // the most recent ones.
76  if (list_.size() >= kMaxErrorsPerExtension) {
77    delete list_.front();
78    list_.pop_front();
79  }
80
81  list_.push_back(error.release());
82  return list_.back();
83}
84
85////////////////////////////////////////////////////////////////////////////////
86// ErrorMap
87ErrorMap::ErrorMap() {
88}
89
90ErrorMap::~ErrorMap() {
91  RemoveAllErrors();
92}
93
94const ErrorList& ErrorMap::GetErrorsForExtension(
95    const std::string& extension_id) const {
96  EntryMap::const_iterator iter = map_.find(extension_id);
97  return iter != map_.end() ? *iter->second->list() : g_empty_error_list.Get();
98}
99
100const ExtensionError* ErrorMap::AddError(scoped_ptr<ExtensionError> error) {
101  EntryMap::iterator iter = map_.find(error->extension_id());
102  if (iter == map_.end()) {
103    iter = map_.insert(std::pair<std::string, ExtensionEntry*>(
104        error->extension_id(), new ExtensionEntry)).first;
105  }
106  return iter->second->AddError(error.Pass());
107}
108
109void ErrorMap::Remove(const std::string& extension_id) {
110  EntryMap::iterator iter = map_.find(extension_id);
111  if (iter == map_.end())
112    return;
113
114  delete iter->second;
115  map_.erase(iter);
116}
117
118void ErrorMap::RemoveErrorsForExtensionOfType(const std::string& extension_id,
119                                              ExtensionError::Type type) {
120  EntryMap::iterator iter = map_.find(extension_id);
121  if (iter != map_.end())
122    iter->second->DeleteErrorsOfType(type);
123}
124
125void ErrorMap::RemoveIncognitoErrors() {
126  for (EntryMap::iterator iter = map_.begin(); iter != map_.end(); ++iter)
127    iter->second->DeleteIncognitoErrors();
128}
129
130void ErrorMap::RemoveAllErrors() {
131  for (EntryMap::iterator iter = map_.begin(); iter != map_.end(); ++iter) {
132    iter->second->DeleteAllErrors();
133    delete iter->second;
134  }
135  map_.clear();
136}
137
138}  // namespace extensions
139