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

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: 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"
11 #include "base/command_line.h"
9 #include "base/lazy_instance.h" 12 #include "base/lazy_instance.h"
13 #include "base/prefs/pref_service.h"
10 #include "base/stl_util.h" 14 #include "base/stl_util.h"
11 #include "chrome/browser/chrome_notification_types.h" 15 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/extensions/extension_system.h" 16 #include "chrome/browser/extensions/extension_system.h"
13 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/common/extensions/extension.h" 18 #include "chrome/common/extensions/extension.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"
24 #include "extensions/common/switches.h"
19 25
20 namespace extensions { 26 namespace extensions {
21 27
22 namespace { 28 namespace {
23 29
24 const size_t kMaxErrorsPerExtension = 100; 30 const size_t kMaxErrorsPerExtension = 100;
25 31
26 // Iterate through an error list and remove and delete all errors which were 32 // Iterate through an error list and remove and delete all errors which were
27 // from an incognito context. 33 // from an incognito context.
28 void DeleteIncognitoErrorsFromList(ErrorConsole::ErrorList* list) { 34 void DeleteIncognitoErrorsFromList(ErrorConsole::ErrorList* list) {
29 ErrorConsole::ErrorList::iterator iter = list->begin(); 35 ErrorConsole::ErrorList::iterator iter = list->begin();
30 while (iter != list->end()) { 36 while (iter != list->end()) {
31 if ((*iter)->from_incognito()) { 37 if ((*iter)->from_incognito()) {
32 delete *iter; 38 delete *iter;
33 iter = list->erase(iter); 39 iter = list->erase(iter);
34 } else { 40 } else {
35 ++iter; 41 ++iter;
36 } 42 }
37 } 43 }
38 } 44 }
39 45
40 base::LazyInstance<ErrorConsole::ErrorList> g_empty_error_list = 46 base::LazyInstance<ErrorConsole::ErrorList> g_empty_error_list =
41 LAZY_INSTANCE_INITIALIZER; 47 LAZY_INSTANCE_INITIALIZER;
42 48
43 } // namespace 49 } // namespace
44 50
45 void ErrorConsole::Observer::OnErrorConsoleDestroyed() { 51 void ErrorConsole::Observer::OnErrorConsoleDestroyed() {
46 } 52 }
47 53
48 ErrorConsole::ErrorConsole(Profile* profile) : profile_(profile) { 54 ErrorConsole::ErrorConsole(Profile* profile) : enabled_(false),
49 registrar_.Add(this, 55 profile_(profile) {
50 chrome::NOTIFICATION_PROFILE_DESTROYED, 56 // If we don't have the necessary CommandLine switch enabled, then return
Yoyo Zhou 2013/08/27 00:41:07 As I mentioned earlier today, take a look at Featu
Devlin 2013/08/27 17:13:56 Done.
51 content::NotificationService::AllBrowserContextsAndSources()); 57 // immediately. Since we never register for any notifications, this ensures
52 registrar_.Add(this, 58 // the ErrorConsole will never be enabled.
53 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 59 if (!CommandLine::ForCurrentProcess()->HasSwitch(
54 content::Source<Profile>(profile_)); 60 switches::kEnableErrorConsole)) {
61 return;
62 }
63
64 pref_registrar_.Init(profile_->GetPrefs());
65 pref_registrar_.Add(prefs::kExtensionsUIDeveloperMode,
66 base::Bind(&ErrorConsole::OnPrefChanged,
67 base::Unretained(this)));
68
69 if (profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode))
70 Enable();
55 } 71 }
56 72
57 ErrorConsole::~ErrorConsole() { 73 ErrorConsole::~ErrorConsole() {
58 FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed()); 74 FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed());
59 RemoveAllErrors(); 75 RemoveAllErrors();
60 } 76 }
61 77
62 // static 78 // static
63 ErrorConsole* ErrorConsole::Get(Profile* profile) { 79 ErrorConsole* ErrorConsole::Get(Profile* profile) {
64 return ExtensionSystem::Get(profile)->error_console(); 80 return ExtensionSystem::Get(profile)->error_console();
65 } 81 }
66 82
67 void ErrorConsole::ReportError(scoped_ptr<const ExtensionError> scoped_error) { 83 void ErrorConsole::ReportError(scoped_ptr<const ExtensionError> error) {
68 DCHECK(thread_checker_.CalledOnValidThread()); 84 DCHECK(thread_checker_.CalledOnValidThread());
69 85
70 const ExtensionError* error = scoped_error.release(); 86 if (!enabled_ || !Extension::IdIsValid(error->extension_id()))
71 // If there are too many errors for an extension already, limit ourselves to 87 return;
72 // the most recent ones. 88
73 ErrorList* error_list = &errors_[error->extension_id()]; 89 // Keep a pointer to the error so we can reference it after |error|'s release
74 if (error_list->size() >= kMaxErrorsPerExtension) { 90 // without keeping track of an index in a list.
75 delete error_list->front(); 91 const ExtensionError* weak_error = error.get();
76 error_list->pop_front(); 92 ErrorList* extension_errors = &errors_[error->extension_id()];
93
94 // First, check if it's a duplicate.
95 for (size_t i = 0; i < extension_errors->size(); ++i) {
96 // If we find a duplicate error, replace the error with the new version.
Yoyo Zhou 2013/08/27 00:41:07 There's no way to see how often a duplicate error
Devlin 2013/08/27 17:13:56 Originally, I was holding off on any of the implem
97 // This can be useful for runtime errors, where we can link to the latest
98 // context, inspectable view, etc.
99 if (error->IsEqual(extension_errors->at(i))) {
100 delete extension_errors->at(i);
101 extension_errors->at(i) = error.release();
Yoyo Zhou 2013/08/27 00:41:07 Could this violate our expectation that the error
Devlin 2013/08/27 17:13:56 Ooh, good point. Fixed.
102 break;
103 }
77 } 104 }
78 error_list->push_back(error);
79 105
80 FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(error)); 106 // If we didn't replace a previous error, then we add the error to the end of
107 // the list.
108 if (error.get()) {
109 // If there are too many errors for an extension already, limit ourselves to
110 // the most recent ones.
111 if (extension_errors->size() >= kMaxErrorsPerExtension) {
112 delete extension_errors->front();
113 extension_errors->pop_front();
114 }
115 extension_errors->push_back(error.release());
116 }
117
118 FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(weak_error));
81 } 119 }
82 120
83 const ErrorConsole::ErrorList& ErrorConsole::GetErrorsForExtension( 121 const ErrorConsole::ErrorList& ErrorConsole::GetErrorsForExtension(
84 const std::string& extension_id) const { 122 const std::string& extension_id) const {
85 ErrorMap::const_iterator iter = errors_.find(extension_id); 123 ErrorMap::const_iterator iter = errors_.find(extension_id);
86 if (iter != errors_.end()) 124 if (iter != errors_.end())
87 return iter->second; 125 return iter->second;
88 return g_empty_error_list.Get(); 126 return g_empty_error_list.Get();
89 } 127 }
90 128
91 void ErrorConsole::AddObserver(Observer* observer) { 129 void ErrorConsole::AddObserver(Observer* observer) {
92 DCHECK(thread_checker_.CalledOnValidThread()); 130 DCHECK(thread_checker_.CalledOnValidThread());
93 observers_.AddObserver(observer); 131 observers_.AddObserver(observer);
94 } 132 }
95 133
96 void ErrorConsole::RemoveObserver(Observer* observer) { 134 void ErrorConsole::RemoveObserver(Observer* observer) {
97 DCHECK(thread_checker_.CalledOnValidThread()); 135 DCHECK(thread_checker_.CalledOnValidThread());
98 observers_.RemoveObserver(observer); 136 observers_.RemoveObserver(observer);
99 } 137 }
100 138
139 void ErrorConsole::OnPrefChanged() {
140 bool developer_mode =
141 profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode);
142
143 if (developer_mode && !enabled_)
144 Enable();
145 else if (!developer_mode && enabled_)
146 Disable();
147 }
148
149 void ErrorConsole::Enable() {
150 enabled_ = true;
151
152 notification_registrar_.Add(
153 this,
154 chrome::NOTIFICATION_PROFILE_DESTROYED,
155 content::NotificationService::AllBrowserContextsAndSources());
156 notification_registrar_.Add(
157 this,
158 chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
159 content::Source<Profile>(profile_));
160 }
161
162 void ErrorConsole::Disable() {
163 notification_registrar_.RemoveAll();
164 RemoveAllErrors();
165 enabled_ = false;
166 }
167
101 void ErrorConsole::RemoveIncognitoErrors() { 168 void ErrorConsole::RemoveIncognitoErrors() {
102 for (ErrorMap::iterator iter = errors_.begin(); 169 for (ErrorMap::iterator iter = errors_.begin();
103 iter != errors_.end(); ++iter) { 170 iter != errors_.end(); ++iter) {
104 DeleteIncognitoErrorsFromList(&(iter->second)); 171 DeleteIncognitoErrorsFromList(&(iter->second));
105 } 172 }
106 } 173 }
107 174
108 void ErrorConsole::RemoveErrorsForExtension(const std::string& extension_id) { 175 void ErrorConsole::RemoveErrorsForExtension(const std::string& extension_id) {
109 ErrorMap::iterator iter = errors_.find(extension_id); 176 ErrorMap::iterator iter = errors_.find(extension_id);
110 if (iter != errors_.end()) { 177 if (iter != errors_.end()) {
(...skipping 25 matching lines...) Expand all
136 // notifications from our own. 203 // notifications from our own.
137 RemoveErrorsForExtension( 204 RemoveErrorsForExtension(
138 content::Details<Extension>(details).ptr()->id()); 205 content::Details<Extension>(details).ptr()->id());
139 break; 206 break;
140 default: 207 default:
141 NOTREACHED(); 208 NOTREACHED();
142 } 209 }
143 } 210 }
144 211
145 } // namespace extensions 212 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698