Add ICU message format support
[chromium-blink-merge.git] / extensions / browser / error_map.cc
blobb0083a89fb7f498ec2f3a7dcd1b157f9c9da3c77
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.
5 #include "extensions/browser/error_map.h"
7 #include "base/lazy_instance.h"
8 #include "base/stl_util.h"
10 namespace extensions {
12 namespace {
14 // The maximum number of errors to be stored per extension.
15 const size_t kMaxErrorsPerExtension = 100;
17 base::LazyInstance<ErrorList> g_empty_error_list = LAZY_INSTANCE_INITIALIZER;
19 // An incrementing counter for the next error id. Overflowing this is very
20 // unlikely, since the number of errors per extension is capped at 100.
21 int kNextErrorId = 1;
23 } // namespace
25 ////////////////////////////////////////////////////////////////////////////////
26 // ErrorMap::Filter
27 ErrorMap::Filter::Filter(const std::string& restrict_to_extension_id,
28 int restrict_to_type,
29 const std::set<int>& restrict_to_ids,
30 bool restrict_to_incognito)
31 : restrict_to_extension_id(restrict_to_extension_id),
32 restrict_to_type(restrict_to_type),
33 restrict_to_ids(restrict_to_ids),
34 restrict_to_incognito(restrict_to_incognito) {
37 ErrorMap::Filter::~Filter() {
40 ErrorMap::Filter ErrorMap::Filter::ErrorsForExtension(
41 const std::string& extension_id) {
42 return Filter(extension_id, -1, std::set<int>(), false);
45 ErrorMap::Filter ErrorMap::Filter::ErrorsForExtensionWithType(
46 const std::string& extension_id,
47 ExtensionError::Type type) {
48 return Filter(extension_id, type, std::set<int>(), false);
51 ErrorMap::Filter ErrorMap::Filter::ErrorsForExtensionWithIds(
52 const std::string& extension_id,
53 const std::set<int>& ids) {
54 return Filter(extension_id, -1, ids, false);
57 ErrorMap::Filter ErrorMap::Filter::ErrorsForExtensionWithTypeAndIds(
58 const std::string& extension_id,
59 ExtensionError::Type type,
60 const std::set<int>& ids) {
61 return Filter(extension_id, type, ids, false);
64 ErrorMap::Filter ErrorMap::Filter::IncognitoErrors() {
65 return Filter(std::string(), -1, std::set<int>(), true);
68 bool ErrorMap::Filter::Matches(const ExtensionError* error) const {
69 if (restrict_to_type != -1 && restrict_to_type != error->type())
70 return false;
71 if (restrict_to_incognito && !error->from_incognito())
72 return false;
73 if (!restrict_to_extension_id.empty() &&
74 error->extension_id() != restrict_to_extension_id)
75 return false;
76 if (!restrict_to_ids.empty() && restrict_to_ids.count(error->id()) == 0)
77 return false;
78 return true;
81 ////////////////////////////////////////////////////////////////////////////////
82 // ErrorMap::ExtensionEntry
83 class ErrorMap::ExtensionEntry {
84 public:
85 ExtensionEntry();
86 ~ExtensionEntry();
88 // Delete any errors in the entry that match the given ids and type, if
89 // provided.
90 // Returns true if any errors were deleted.
91 bool DeleteErrors(const ErrorMap::Filter& filter);
92 // Delete all errors in the entry.
93 void DeleteAllErrors();
95 // Add the error to the list, and return a weak reference.
96 const ExtensionError* AddError(scoped_ptr<ExtensionError> error);
98 const ErrorList* list() const { return &list_; }
100 private:
101 // The list of all errors associated with the extension. The errors are
102 // owned by the Entry (in turn owned by the ErrorMap) and are deleted upon
103 // destruction.
104 ErrorList list_;
106 DISALLOW_COPY_AND_ASSIGN(ExtensionEntry);
109 ErrorMap::ExtensionEntry::ExtensionEntry() {
112 ErrorMap::ExtensionEntry::~ExtensionEntry() {
113 DeleteAllErrors();
116 bool ErrorMap::ExtensionEntry::DeleteErrors(const Filter& filter) {
117 bool deleted = false;
118 for (ErrorList::iterator iter = list_.begin(); iter != list_.end();) {
119 if (filter.Matches(*iter)) {
120 delete *iter;
121 iter = list_.erase(iter);
122 deleted = true;
123 } else {
124 ++iter;
127 return deleted;
130 void ErrorMap::ExtensionEntry::DeleteAllErrors() {
131 STLDeleteContainerPointers(list_.begin(), list_.end());
132 list_.clear();
135 const ExtensionError* ErrorMap::ExtensionEntry::AddError(
136 scoped_ptr<ExtensionError> error) {
137 for (ErrorList::iterator iter = list_.begin(); iter != list_.end(); ++iter) {
138 // If we find a duplicate error, remove the old error and add the new one,
139 // incrementing the occurrence count of the error. We use the new error
140 // for runtime errors, so we can link to the latest context, inspectable
141 // view, etc.
142 if (error->IsEqual(*iter)) {
143 error->set_occurrences((*iter)->occurrences() + 1);
144 error->set_id((*iter)->id());
145 delete *iter;
146 list_.erase(iter);
147 break;
151 // If there are too many errors for an extension already, limit ourselves to
152 // the most recent ones.
153 if (list_.size() >= kMaxErrorsPerExtension) {
154 delete list_.front();
155 list_.pop_front();
158 if (error->id() == 0)
159 error->set_id(kNextErrorId++);
161 list_.push_back(error.release());
162 return list_.back();
165 ////////////////////////////////////////////////////////////////////////////////
166 // ErrorMap
167 ErrorMap::ErrorMap() {
170 ErrorMap::~ErrorMap() {
171 RemoveAllErrors();
174 const ErrorList& ErrorMap::GetErrorsForExtension(
175 const std::string& extension_id) const {
176 EntryMap::const_iterator iter = map_.find(extension_id);
177 return iter != map_.end() ? *iter->second->list() : g_empty_error_list.Get();
180 const ExtensionError* ErrorMap::AddError(scoped_ptr<ExtensionError> error) {
181 EntryMap::iterator iter = map_.find(error->extension_id());
182 if (iter == map_.end()) {
183 iter = map_.insert(std::pair<std::string, ExtensionEntry*>(
184 error->extension_id(), new ExtensionEntry)).first;
186 return iter->second->AddError(error.Pass());
189 void ErrorMap::RemoveErrors(const Filter& filter,
190 std::set<std::string>* affected_ids) {
191 if (!filter.restrict_to_extension_id.empty()) {
192 EntryMap::iterator iter = map_.find(filter.restrict_to_extension_id);
193 if (iter != map_.end()) {
194 if (iter->second->DeleteErrors(filter) && affected_ids)
195 affected_ids->insert(filter.restrict_to_extension_id);
197 } else {
198 for (auto& key_val : map_) {
199 if (key_val.second->DeleteErrors(filter) && affected_ids)
200 affected_ids->insert(key_val.first);
205 void ErrorMap::RemoveAllErrors() {
206 for (EntryMap::iterator iter = map_.begin(); iter != map_.end(); ++iter)
207 delete iter->second;
208 map_.clear();
211 } // namespace extensions