diff options
author | rdevlin.cronin <rdevlin.cronin@chromium.org> | 2015-03-20 17:56:30 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-21 00:57:07 +0000 |
commit | c799f9f7755bb466fdc4cbd980a3b64071bbcd03 (patch) | |
tree | a9ac2b20f825b7d58957fef8afdd82b5df8f9a16 /extensions | |
parent | e879c2bb12d35c171e6263aba21e85763e0799cc (diff) | |
download | chromium_src-c799f9f7755bb466fdc4cbd980a3b64071bbcd03.zip chromium_src-c799f9f7755bb466fdc4cbd980a3b64071bbcd03.tar.gz chromium_src-c799f9f7755bb466fdc4cbd980a3b64071bbcd03.tar.bz2 |
[Extensions] Add a developerPrivate.deleteExtensionErrors function
Add a developerPrivate API function for removing extension errors.
BUG=TBD
Review URL: https://codereview.chromium.org/1014323003
Cr-Commit-Position: refs/heads/master@{#321673}
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/browser/error_map.cc | 148 | ||||
-rw-r--r-- | extensions/browser/error_map.h | 67 | ||||
-rw-r--r-- | extensions/browser/error_map_unittest.cc | 43 | ||||
-rw-r--r-- | extensions/browser/extension_error.cc | 1 | ||||
-rw-r--r-- | extensions/browser/extension_error.h | 8 | ||||
-rw-r--r-- | extensions/browser/extension_error_test_util.h | 3 | ||||
-rw-r--r-- | extensions/browser/extension_function_histogram_value.h | 1 |
7 files changed, 179 insertions, 92 deletions
diff --git a/extensions/browser/error_map.cc b/extensions/browser/error_map.cc index dfcef9f..0495ae08 100644 --- a/extensions/browser/error_map.cc +++ b/extensions/browser/error_map.cc @@ -6,9 +6,9 @@ #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. @@ -16,10 +16,95 @@ const size_t kMaxErrorsPerExtension = 100; base::LazyInstance<ErrorList> g_empty_error_list = LAZY_INSTANCE_INITIALIZER; +// An incrementing counter for the next error id. Overflowing this is very +// unlikely, since the number of errors per extension is capped at 100. +int kNextErrorId = 1; + } // namespace //////////////////////////////////////////////////////////////////////////////// +// ErrorMap::Filter +ErrorMap::Filter::Filter(const std::string& restrict_to_extension_id, + int restrict_to_type, + const std::set<int>& restrict_to_ids, + bool restrict_to_incognito) + : restrict_to_extension_id(restrict_to_extension_id), + restrict_to_type(restrict_to_type), + restrict_to_ids(restrict_to_ids), + restrict_to_incognito(restrict_to_incognito) { +} + +ErrorMap::Filter::~Filter() { +} + +ErrorMap::Filter ErrorMap::Filter::ErrorsForExtension( + const std::string& extension_id) { + return Filter(extension_id, -1, std::set<int>(), false); +} + +ErrorMap::Filter ErrorMap::Filter::ErrorsForExtensionWithType( + const std::string& extension_id, + ExtensionError::Type type) { + return Filter(extension_id, type, std::set<int>(), false); +} + +ErrorMap::Filter ErrorMap::Filter::ErrorsForExtensionWithIds( + const std::string& extension_id, + const std::set<int>& ids) { + return Filter(extension_id, -1, ids, false); +} + +ErrorMap::Filter ErrorMap::Filter::ErrorsForExtensionWithTypeAndIds( + const std::string& extension_id, + ExtensionError::Type type, + const std::set<int>& ids) { + return Filter(extension_id, type, ids, false); +} + +ErrorMap::Filter ErrorMap::Filter::IncognitoErrors() { + return Filter(std::string(), -1, std::set<int>(), true); +} + +bool ErrorMap::Filter::Matches(const ExtensionError* error) const { + if (restrict_to_type != -1 && restrict_to_type != error->type()) + return false; + if (restrict_to_incognito && !error->from_incognito()) + return false; + if (!restrict_to_extension_id.empty() && + error->extension_id() != restrict_to_extension_id) + return false; + if (!restrict_to_ids.empty() && restrict_to_ids.count(error->id()) == 0) + return false; + return true; +} + +//////////////////////////////////////////////////////////////////////////////// // ErrorMap::ExtensionEntry +class ErrorMap::ExtensionEntry { + public: + ExtensionEntry(); + ~ExtensionEntry(); + + // Delete any errors in the entry that match the given ids and type, if + // provided. + void DeleteErrors(const ErrorMap::Filter& filter); + // Delete all errors in the entry. + void DeleteAllErrors(); + + // Add the error to the list, and return a weak reference. + const ExtensionError* AddError(scoped_ptr<ExtensionError> error); + + const ErrorList* list() const { return &list_; } + + private: + // The list of all errors associated with the extension. The errors are + // owned by the Entry (in turn owned by the ErrorMap) and are deleted upon + // destruction. + ErrorList list_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionEntry); +}; + ErrorMap::ExtensionEntry::ExtensionEntry() { } @@ -27,15 +112,9 @@ 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()) { +void ErrorMap::ExtensionEntry::DeleteErrors(const Filter& filter) { + for (ErrorList::iterator iter = list_.begin(); iter != list_.end();) { + if (filter.Matches(*iter)) { delete *iter; iter = list_.erase(iter); } else { @@ -44,16 +123,9 @@ void ErrorMap::ExtensionEntry::DeleteIncognitoErrors() { } } -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; - } - } +void ErrorMap::ExtensionEntry::DeleteAllErrors() { + STLDeleteContainerPointers(list_.begin(), list_.end()); + list_.clear(); } const ExtensionError* ErrorMap::ExtensionEntry::AddError( @@ -65,6 +137,7 @@ const ExtensionError* ErrorMap::ExtensionEntry::AddError( // view, etc. if (error->IsEqual(*iter)) { error->set_occurrences((*iter)->occurrences() + 1); + error->set_id((*iter)->id()); delete *iter; list_.erase(iter); break; @@ -78,6 +151,9 @@ const ExtensionError* ErrorMap::ExtensionEntry::AddError( list_.pop_front(); } + if (error->id() == 0) + error->set_id(kNextErrorId++); + list_.push_back(error.release()); return list_.back(); } @@ -106,32 +182,20 @@ const ExtensionError* ErrorMap::AddError(scoped_ptr<ExtensionError> error) { 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::RemoveErrors(const Filter& filter) { + if (!filter.restrict_to_extension_id.empty()) { + EntryMap::iterator iter = map_.find(filter.restrict_to_extension_id); + if (iter != map_.end()) + iter->second->DeleteErrors(filter); + } else { + for (auto& key_val : map_) + key_val.second->DeleteErrors(filter); + } } void ErrorMap::RemoveAllErrors() { - for (EntryMap::iterator iter = map_.begin(); iter != map_.end(); ++iter) { - iter->second->DeleteAllErrors(); + for (EntryMap::iterator iter = map_.begin(); iter != map_.end(); ++iter) delete iter->second; - } map_.clear(); } diff --git a/extensions/browser/error_map.h b/extensions/browser/error_map.h index 216d136..f0e6b2c 100644 --- a/extensions/browser/error_map.h +++ b/extensions/browser/error_map.h @@ -7,6 +7,7 @@ #include <deque> #include <map> +#include <set> #include <string> #include "base/basictypes.h" @@ -25,19 +26,43 @@ class ErrorMap { ErrorMap(); ~ErrorMap(); + struct Filter { + Filter(const std::string& restrict_to_extension_id, + int restrict_to_type, + const std::set<int>& restrict_to_ids, + bool restrict_to_incognito); + ~Filter(); + + // Convenience methods to get a specific type of filter. Prefer these over + // the constructor when possible. + static Filter ErrorsForExtension(const std::string& extension_id); + static Filter ErrorsForExtensionWithType(const std::string& extension_id, + ExtensionError::Type type); + static Filter ErrorsForExtensionWithIds(const std::string& extension_id, + const std::set<int>& ids); + static Filter ErrorsForExtensionWithTypeAndIds( + const std::string& extension_id, + ExtensionError::Type type, + const std::set<int>& ids); + static Filter IncognitoErrors(); + + bool Matches(const ExtensionError* error) const; + + const std::string restrict_to_extension_id; + const int restrict_to_type; + const std::set<int> restrict_to_ids; + const bool restrict_to_incognito; + }; + // Return the list of all errors associated with the given extension. const ErrorList& GetErrorsForExtension(const std::string& extension_id) const; // Add the |error| to the ErrorMap. const ExtensionError* AddError(scoped_ptr<ExtensionError> error); - // Remove an extension from the ErrorMap, deleting all associated errors. - void Remove(const std::string& extension_id); - // Remove all errors of a given type for an extension. - void RemoveErrorsForExtensionOfType(const std::string& extension_id, - ExtensionError::Type type); - // Remove all incognito errors for all extensions. - void RemoveIncognitoErrors(); + // Removes errors that match the given |filter| from the map. + void RemoveErrors(const Filter& filter); + // Remove all errors for all extensions, and clear the map. void RemoveAllErrors(); @@ -46,32 +71,8 @@ class ErrorMap { private: // An Entry is created for each Extension ID, and stores the errors related to // that Extension. - class ExtensionEntry { - public: - ExtensionEntry(); - ~ExtensionEntry(); - - // Delete all errors associated with this extension. - void DeleteAllErrors(); - // Delete all incognito errors associated with this extension. - void DeleteIncognitoErrors(); - // Delete all errors of the given |type| associated with this extension. - void DeleteErrorsOfType(ExtensionError::Type type); - - // Add the error to the list, and return a weak reference. - const ExtensionError* AddError(scoped_ptr<ExtensionError> error); - - const ErrorList* list() const { return &list_; } - - private: - // The list of all errors associated with the extension. The errors are - // owned by the Entry (in turn owned by the ErrorMap) and are deleted upon - // destruction. - ErrorList list_; - - DISALLOW_COPY_AND_ASSIGN(ExtensionEntry); - }; - typedef std::map<std::string, ExtensionEntry*> EntryMap; + class ExtensionEntry; + using EntryMap = std::map<std::string, ExtensionEntry*>; // The mapping between Extension IDs and their corresponding Entries. EntryMap map_; diff --git a/extensions/browser/error_map_unittest.cc b/extensions/browser/error_map_unittest.cc index d393624..b8ae20d 100644 --- a/extensions/browser/error_map_unittest.cc +++ b/extensions/browser/error_map_unittest.cc @@ -16,6 +16,7 @@ namespace extensions { using error_test_util::CreateNewRuntimeError; +using error_test_util::CreateNewManifestError; class ErrorMapUnitTest : public testing::Test { public: @@ -44,39 +45,53 @@ TEST_F(ErrorMapUnitTest, AddAndRemoveErrors) { // There should only be one entry in the map, since errors are stored in lists // keyed by extension id. - ASSERT_EQ(1u, errors_.size()); + EXPECT_EQ(1u, errors_.size()); - ASSERT_EQ(kNumTotalErrors, errors_.GetErrorsForExtension(kId).size()); + EXPECT_EQ(kNumTotalErrors, errors_.GetErrorsForExtension(kId).size()); // Remove the incognito errors; three errors should remain, and all should // be from non-incognito contexts. - errors_.RemoveIncognitoErrors(); + errors_.RemoveErrors(ErrorMap::Filter::IncognitoErrors()); const ErrorList& list = errors_.GetErrorsForExtension(kId); - ASSERT_EQ(kNumNonIncognitoErrors, list.size()); + EXPECT_EQ(kNumNonIncognitoErrors, list.size()); for (size_t i = 0; i < list.size(); ++i) - ASSERT_FALSE(list[i]->from_incognito()); + EXPECT_FALSE(list[i]->from_incognito()); // Add another error for a different extension id. const std::string kSecondId = crx_file::id_util::GenerateId("id2"); - ASSERT_TRUE(errors_.AddError(CreateNewRuntimeError(kSecondId, "foo"))); + EXPECT_TRUE(errors_.AddError(CreateNewRuntimeError(kSecondId, "foo"))); // There should be two entries now, one for each id, and there should be one // error for the second extension. - ASSERT_EQ(2u, errors_.size()); - ASSERT_EQ(1u, errors_.GetErrorsForExtension(kSecondId).size()); + EXPECT_EQ(2u, errors_.size()); + EXPECT_EQ(1u, errors_.GetErrorsForExtension(kSecondId).size()); // Remove all errors for the second id. - errors_.Remove(kSecondId); - ASSERT_EQ(1u, errors_.size()); - ASSERT_EQ(0u, errors_.GetErrorsForExtension(kSecondId).size()); + errors_.RemoveErrors(ErrorMap::Filter::ErrorsForExtension(kSecondId)); + EXPECT_EQ(0u, errors_.GetErrorsForExtension(kSecondId).size()); // First extension should be unaffected. - ASSERT_EQ(kNumNonIncognitoErrors, + EXPECT_EQ(kNumNonIncognitoErrors, errors_.GetErrorsForExtension(kId).size()); + + errors_.AddError(CreateNewManifestError(kId, "manifest error")); + EXPECT_EQ(kNumNonIncognitoErrors + 1, errors_.GetErrorsForExtension(kId).size()); + errors_.RemoveErrors(ErrorMap::Filter::ErrorsForExtensionWithType( + kId, ExtensionError::MANIFEST_ERROR)); + EXPECT_EQ(kNumNonIncognitoErrors, errors_.GetErrorsForExtension(kId).size()); + + const ExtensionError* added_error = + errors_.AddError(CreateNewManifestError(kId, "manifest error2")); + EXPECT_EQ(kNumNonIncognitoErrors + 1, + errors_.GetErrorsForExtension(kId).size()); + std::set<int> ids; + ids.insert(added_error->id()); + errors_.RemoveErrors(ErrorMap::Filter::ErrorsForExtensionWithIds(kId, ids)); + EXPECT_EQ(kNumNonIncognitoErrors, errors_.GetErrorsForExtension(kId).size()); // Remove remaining errors. errors_.RemoveAllErrors(); - ASSERT_EQ(0u, errors_.size()); - ASSERT_EQ(0u, errors_.GetErrorsForExtension(kId).size()); + EXPECT_EQ(0u, errors_.size()); + EXPECT_EQ(0u, errors_.GetErrorsForExtension(kId).size()); } // Test that if we add enough errors, only the most recent diff --git a/extensions/browser/extension_error.cc b/extensions/browser/extension_error.cc index 19a31ea..605efbb 100644 --- a/extensions/browser/extension_error.cc +++ b/extensions/browser/extension_error.cc @@ -33,6 +33,7 @@ ExtensionError::ExtensionError(Type type, const base::string16& message) : type_(type), extension_id_(extension_id), + id_(0), from_incognito_(from_incognito), level_(level), source_(source), diff --git a/extensions/browser/extension_error.h b/extensions/browser/extension_error.h index ba44d55..7628f7e 100644 --- a/extensions/browser/extension_error.h +++ b/extensions/browser/extension_error.h @@ -24,9 +24,9 @@ namespace extensions { class ExtensionError { public: enum Type { - MANIFEST_ERROR, + MANIFEST_ERROR = 0, RUNTIME_ERROR, - NUM_ERROR_TYPES // Put new values above this. + NUM_ERROR_TYPES, // Put new values above this. }; virtual ~ExtensionError(); @@ -42,6 +42,8 @@ class ExtensionError { Type type() const { return type_; } const std::string& extension_id() const { return extension_id_; } + int id() const { return id_; } + void set_id(int id) { id_ = id; } bool from_incognito() const { return from_incognito_; } logging::LogSeverity level() const { return level_; } const base::string16& source() const { return source_; } @@ -71,6 +73,8 @@ class ExtensionError { Type type_; // The ID of the extension which caused the error. std::string extension_id_; + // The id of this particular error. This can be zero if the id is never set. + int id_; // Whether or not the error was caused while incognito. bool from_incognito_; // The severity level of the error. diff --git a/extensions/browser/extension_error_test_util.h b/extensions/browser/extension_error_test_util.h index 4866cef..6ea2da6 100644 --- a/extensions/browser/extension_error_test_util.h +++ b/extensions/browser/extension_error_test_util.h @@ -27,7 +27,8 @@ scoped_ptr<ExtensionError> CreateNewRuntimeError( // Create a new ManifestError. scoped_ptr<ExtensionError> CreateNewManifestError( - const std::string& extension_id, const std::string& mnessage); + const std::string& extension_id, + const std::string& message); } // namespace error_test_util } // namespace extensions diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 3cbb60b..f3d0785 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h @@ -1040,6 +1040,7 @@ enum HistogramValue { DEVELOPERPRIVATE_GETEXTENSIONINFO, FILEMANAGERPRIVATE_ENABLEEXTERNALFILESCHEME, DEVELOPERPRIVATE_UPDATEEXTENSIONCONFIGURATION, + DEVELOPERPRIVATE_DELETEEXTENSIONERRORS, // Last entry: Add new entries above and ensure to update // tools/metrics/histograms/histograms.xml. ENUM_BOUNDARY |