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 11 namespace extensions { 12 namespace { 13 14 // The maximum number of errors to be stored per extension. 15 const size_t kMaxErrorsPerExtension = 100; 16 17 base::LazyInstance<ErrorList> g_empty_error_list = LAZY_INSTANCE_INITIALIZER; 18 19 } // namespace 20 21 //////////////////////////////////////////////////////////////////////////////// 22 // ErrorMap::ExtensionEntry 23 ErrorMap::ExtensionEntry::ExtensionEntry() { 24 } 25 26 ErrorMap::ExtensionEntry::~ExtensionEntry() { 27 DeleteAllErrors(); 28 } 29 30 void ErrorMap::ExtensionEntry::DeleteAllErrors() { 31 STLDeleteContainerPointers(list_.begin(), list_.end()); 32 list_.clear(); 33 } 34 35 void 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 47 void 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 59 const 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 87 ErrorMap::ErrorMap() { 88 } 89 90 ErrorMap::~ErrorMap() { 91 RemoveAllErrors(); 92 } 93 94 const 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 100 const 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 109 void 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 118 void 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 125 void ErrorMap::RemoveIncognitoErrors() { 126 for (EntryMap::iterator iter = map_.begin(); iter != map_.end(); ++iter) 127 iter->second->DeleteIncognitoErrors(); 128 } 129 130 void 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