Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(307)

Side by Side Diff: chrome/browser/extensions/error_console/error_console.cc

Issue 23311011: ErrorConsole Switch, Duplicate Error Detection, Dev Mode Check (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Convert to FeatureSwitch, add Occurrence Count Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/error_console/error_console.h" 5 #include "chrome/browser/extensions/error_console/error_console.h"
6 6
7 #include <list> 7 #include <list>
8 8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
9 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/prefs/pref_service.h"
10 #include "base/stl_util.h" 13 #include "base/stl_util.h"
11 #include "chrome/browser/chrome_notification_types.h" 14 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/extensions/extension_system.h" 15 #include "chrome/browser/extensions/extension_system.h"
13 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/common/extensions/extension.h" 17 #include "chrome/common/extensions/extension.h"
18 #include "chrome/common/extensions/feature_switch.h"
19 #include "chrome/common/pref_names.h"
15 #include "content/public/browser/notification_details.h" 20 #include "content/public/browser/notification_details.h"
16 #include "content/public/browser/notification_service.h" 21 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/notification_source.h" 22 #include "content/public/browser/notification_source.h"
18 #include "extensions/common/constants.h" 23 #include "extensions/common/constants.h"
19 24
20 namespace extensions { 25 namespace extensions {
21 26
22 namespace { 27 namespace {
23 28
24 const size_t kMaxErrorsPerExtension = 100; 29 const size_t kMaxErrorsPerExtension = 100;
(...skipping 13 matching lines...) Expand all
38 } 43 }
39 44
40 base::LazyInstance<ErrorConsole::ErrorList> g_empty_error_list = 45 base::LazyInstance<ErrorConsole::ErrorList> g_empty_error_list =
41 LAZY_INSTANCE_INITIALIZER; 46 LAZY_INSTANCE_INITIALIZER;
42 47
43 } // namespace 48 } // namespace
44 49
45 void ErrorConsole::Observer::OnErrorConsoleDestroyed() { 50 void ErrorConsole::Observer::OnErrorConsoleDestroyed() {
46 } 51 }
47 52
48 ErrorConsole::ErrorConsole(Profile* profile) : profile_(profile) { 53 ErrorConsole::ErrorConsole(Profile* profile) : enabled_(false),
49 registrar_.Add(this, 54 profile_(profile) {
50 chrome::NOTIFICATION_PROFILE_DESTROYED, 55 // If we don't have the necessary FeatureSwitch enabled, then return
51 content::NotificationService::AllBrowserContextsAndSources()); 56 // immediately. Since we never register for any notifications, this ensures
52 registrar_.Add(this, 57 // the ErrorConsole will never be enabled.
53 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 58 if (!FeatureSwitch::error_console()->IsEnabled())
54 content::Source<Profile>(profile_)); 59 return;
60
61 pref_registrar_.Init(profile_->GetPrefs());
62 pref_registrar_.Add(prefs::kExtensionsUIDeveloperMode,
63 base::Bind(&ErrorConsole::OnPrefChanged,
64 base::Unretained(this)));
65
66 if (profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode))
67 Enable();
55 } 68 }
56 69
57 ErrorConsole::~ErrorConsole() { 70 ErrorConsole::~ErrorConsole() {
58 FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed()); 71 FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed());
59 RemoveAllErrors(); 72 RemoveAllErrors();
60 } 73 }
61 74
62 // static 75 // static
63 ErrorConsole* ErrorConsole::Get(Profile* profile) { 76 ErrorConsole* ErrorConsole::Get(Profile* profile) {
64 return ExtensionSystem::Get(profile)->error_console(); 77 return ExtensionSystem::Get(profile)->error_console();
65 } 78 }
66 79
67 void ErrorConsole::ReportError(scoped_ptr<const ExtensionError> scoped_error) { 80 void ErrorConsole::ReportError(scoped_ptr<ExtensionError> error) {
68 DCHECK(thread_checker_.CalledOnValidThread()); 81 DCHECK(thread_checker_.CalledOnValidThread());
69 82
70 const ExtensionError* error = scoped_error.release(); 83 if (!enabled_ || !Extension::IdIsValid(error->extension_id()))
84 return;
85
86 ErrorList* extension_errors = &errors_[error->extension_id()];
87
88 // First, check if it's a duplicate.
89 for (ErrorList::iterator iter = extension_errors->begin();
90 iter != extension_errors->end(); ++iter) {
91 // If we find a duplicate error, remove the old error and add the new one,
92 // incrementing the occurrence count of the error. We use the new error
93 // for runtime errors, so we can link to the latest context, inspectable
94 // view, etc.
95 if (error->IsEqual(*iter)) {
96 error->set_occurrences((*iter)->occurrences() + 1);
97 delete *iter;
98 extension_errors->erase(iter);
99 break;
100 }
101 }
102
71 // If there are too many errors for an extension already, limit ourselves to 103 // If there are too many errors for an extension already, limit ourselves to
72 // the most recent ones. 104 // the most recent ones.
73 ErrorList* error_list = &errors_[error->extension_id()]; 105 if (extension_errors->size() >= kMaxErrorsPerExtension) {
74 if (error_list->size() >= kMaxErrorsPerExtension) { 106 delete extension_errors->front();
75 delete error_list->front(); 107 extension_errors->pop_front();
76 error_list->pop_front();
77 } 108 }
78 error_list->push_back(error);
79 109
80 FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(error)); 110 extension_errors->push_back(error.release());
111
112 FOR_EACH_OBSERVER(
113 Observer, observers_, OnErrorAdded(extension_errors->back()));
81 } 114 }
82 115
83 const ErrorConsole::ErrorList& ErrorConsole::GetErrorsForExtension( 116 const ErrorConsole::ErrorList& ErrorConsole::GetErrorsForExtension(
84 const std::string& extension_id) const { 117 const std::string& extension_id) const {
85 ErrorMap::const_iterator iter = errors_.find(extension_id); 118 ErrorMap::const_iterator iter = errors_.find(extension_id);
86 if (iter != errors_.end()) 119 if (iter != errors_.end())
87 return iter->second; 120 return iter->second;
88 return g_empty_error_list.Get(); 121 return g_empty_error_list.Get();
89 } 122 }
90 123
91 void ErrorConsole::AddObserver(Observer* observer) { 124 void ErrorConsole::AddObserver(Observer* observer) {
92 DCHECK(thread_checker_.CalledOnValidThread()); 125 DCHECK(thread_checker_.CalledOnValidThread());
93 observers_.AddObserver(observer); 126 observers_.AddObserver(observer);
94 } 127 }
95 128
96 void ErrorConsole::RemoveObserver(Observer* observer) { 129 void ErrorConsole::RemoveObserver(Observer* observer) {
97 DCHECK(thread_checker_.CalledOnValidThread()); 130 DCHECK(thread_checker_.CalledOnValidThread());
98 observers_.RemoveObserver(observer); 131 observers_.RemoveObserver(observer);
99 } 132 }
100 133
134 void ErrorConsole::OnPrefChanged() {
135 bool should_enable =
136 profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode) &&
137 FeatureSwitch::error_console()->IsEnabled();
Yoyo Zhou 2013/08/27 17:28:00 It doesn't make sense to test for the FeatureSwitc
Devlin 2013/08/27 18:25:55 My thought was to protect a little against ScopedO
Yoyo Zhou 2013/08/27 18:48:43 Yeah, as you noted, because of the lack of observe
138
139 if (should_enable && !enabled_)
140 Enable(ExtensionSystem::Get(profile_)->extension_service());
141 else if (!should_enable && enabled_)
142 Disable();
143 }
144
145 void ErrorConsole::Enable(ExtensionService* extension_service) {
146 enabled_ = true;
147
148 notification_registrar_.Add(
149 this,
150 chrome::NOTIFICATION_PROFILE_DESTROYED,
151 content::NotificationService::AllBrowserContextsAndSources());
152 notification_registrar_.Add(
153 this,
154 chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
155 content::Source<Profile>(profile_));
156 }
157
158 void ErrorConsole::Disable() {
159 notification_registrar_.RemoveAll();
160 RemoveAllErrors();
161 enabled_ = false;
162 }
163
101 void ErrorConsole::RemoveIncognitoErrors() { 164 void ErrorConsole::RemoveIncognitoErrors() {
102 for (ErrorMap::iterator iter = errors_.begin(); 165 for (ErrorMap::iterator iter = errors_.begin();
103 iter != errors_.end(); ++iter) { 166 iter != errors_.end(); ++iter) {
104 DeleteIncognitoErrorsFromList(&(iter->second)); 167 DeleteIncognitoErrorsFromList(&(iter->second));
105 } 168 }
106 } 169 }
107 170
108 void ErrorConsole::RemoveErrorsForExtension(const std::string& extension_id) { 171 void ErrorConsole::RemoveErrorsForExtension(const std::string& extension_id) {
109 ErrorMap::iterator iter = errors_.find(extension_id); 172 ErrorMap::iterator iter = errors_.find(extension_id);
110 if (iter != errors_.end()) { 173 if (iter != errors_.end()) {
(...skipping 25 matching lines...) Expand all
136 // notifications from our own. 199 // notifications from our own.
137 RemoveErrorsForExtension( 200 RemoveErrorsForExtension(
138 content::Details<Extension>(details).ptr()->id()); 201 content::Details<Extension>(details).ptr()->id());
139 break; 202 break;
140 default: 203 default:
141 NOTREACHED(); 204 NOTREACHED();
142 } 205 }
143 } 206 }
144 207
145 } // namespace extensions 208 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698