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

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

Issue 22938005: Add ErrorConsole UI for Extension Install Warnings (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@dc_ec_install_warnings
Patch Set: Created 7 years, 4 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 #include <vector>
8 9
9 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
10 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chrome_notification_types.h" 13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/extensions/extension_service.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/extension_set.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;
25 30
26 // Iterate through an error list and remove and delete all errors which were 31 // Iterate through an error list and remove and delete all errors which were
27 // from an incognito context. 32 // from an incognito context.
28 void DeleteIncognitoErrorsFromList(ErrorConsole::ErrorList* list) { 33 void DeleteIncognitoErrorsFromList(ErrorConsole::ErrorList* list) {
29 ErrorConsole::ErrorList::iterator iter = list->begin(); 34 ErrorConsole::ErrorList::iterator iter = list->begin();
30 while (iter != list->end()) { 35 while (iter != list->end()) {
31 if ((*iter)->from_incognito()) { 36 if ((*iter)->from_incognito()) {
32 delete *iter; 37 delete *iter;
33 iter = list->erase(iter); 38 iter = list->erase(iter);
34 } else { 39 } else {
35 ++iter; 40 ++iter;
36 } 41 }
37 } 42 }
38 } 43 }
39 44
45 // Iterate through an error list and remove and delete all errors of a given
46 // |type|.
47 void DeleteErrorsOfTypeFromList(ErrorConsole::ErrorList* list,
48 ExtensionError::Type type) {
49 ErrorConsole::ErrorList::iterator iter = list->begin();
50 while (iter != list->end()) {
51 if ((*iter)->type() == type) {
52 delete *iter;
53 iter = list->erase(iter);
54 } else {
55 ++iter;
56 }
57 }
58 }
59
40 base::LazyInstance<ErrorConsole::ErrorList> g_empty_error_list = 60 base::LazyInstance<ErrorConsole::ErrorList> g_empty_error_list =
41 LAZY_INSTANCE_INITIALIZER; 61 LAZY_INSTANCE_INITIALIZER;
42 62
43 } // namespace 63 } // namespace
44 64
45 void ErrorConsole::Observer::OnErrorConsoleDestroyed() { 65 void ErrorConsole::Observer::OnErrorConsoleDestroyed() {
46 } 66 }
47 67
48 ErrorConsole::ErrorConsole(Profile* profile) : profile_(profile) { 68 ErrorConsole::ErrorConsole(Profile* profile,
49 registrar_.Add(this, 69 ExtensionService* extension_service)
50 chrome::NOTIFICATION_PROFILE_DESTROYED, 70 : enabled_(false), profile_(profile) {
51 content::NotificationService::AllBrowserContextsAndSources()); 71 pref_registrar_.Init(profile_->GetPrefs());
52 registrar_.Add(this, 72 pref_registrar_.Add(prefs::kExtensionsUIDeveloperMode,
53 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 73 base::Bind(&ErrorConsole::OnPrefChanged,
54 content::Source<Profile>(profile_)); 74 base::Unretained(this)));
75
76 if (profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode))
77 Enable(extension_service);
55 } 78 }
56 79
57 ErrorConsole::~ErrorConsole() { 80 ErrorConsole::~ErrorConsole() {
58 FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed()); 81 FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed());
59 RemoveAllErrors(); 82 RemoveAllErrors();
60 } 83 }
61 84
62 // static 85 // static
63 ErrorConsole* ErrorConsole::Get(Profile* profile) { 86 ErrorConsole* ErrorConsole::Get(Profile* profile) {
64 return ExtensionSystem::Get(profile)->error_console(); 87 return ExtensionSystem::Get(profile)->error_console();
65 } 88 }
66 89
67 void ErrorConsole::ReportError(scoped_ptr<const ExtensionError> scoped_error) { 90 void ErrorConsole::ReportError(scoped_ptr<const ExtensionError> scoped_error) {
68 DCHECK(thread_checker_.CalledOnValidThread()); 91 DCHECK(thread_checker_.CalledOnValidThread());
92 if (!enabled_)
93 return;
69 94
70 const ExtensionError* error = scoped_error.release(); 95 const ExtensionError* error = scoped_error.release();
96 const ErrorList& extension_errors =
97 GetErrorsForExtension(error->extension_id());
98 for (ErrorList::const_iterator iter = extension_errors.begin();
99 iter != extension_errors.end(); ++iter) {
100 if (error->IsEqual(*iter)) { // duplicate error thrown; ignore it.
101 delete error;
102 return;
103 }
104 }
105
71 // If there are too many errors for an extension already, limit ourselves to 106 // If there are too many errors for an extension already, limit ourselves to
72 // the most recent ones. 107 // the most recent ones.
73 ErrorList* error_list = &errors_[error->extension_id()]; 108 ErrorList* error_list = &errors_[error->extension_id()];
74 if (error_list->size() >= kMaxErrorsPerExtension) { 109 if (error_list->size() >= kMaxErrorsPerExtension) {
75 delete error_list->front(); 110 delete error_list->front();
76 error_list->pop_front(); 111 error_list->pop_front();
77 } 112 }
78 error_list->push_back(error); 113 error_list->push_back(error);
79 114
80 FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(error)); 115 FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(error));
(...skipping 10 matching lines...) Expand all
91 void ErrorConsole::AddObserver(Observer* observer) { 126 void ErrorConsole::AddObserver(Observer* observer) {
92 DCHECK(thread_checker_.CalledOnValidThread()); 127 DCHECK(thread_checker_.CalledOnValidThread());
93 observers_.AddObserver(observer); 128 observers_.AddObserver(observer);
94 } 129 }
95 130
96 void ErrorConsole::RemoveObserver(Observer* observer) { 131 void ErrorConsole::RemoveObserver(Observer* observer) {
97 DCHECK(thread_checker_.CalledOnValidThread()); 132 DCHECK(thread_checker_.CalledOnValidThread());
98 observers_.RemoveObserver(observer); 133 observers_.RemoveObserver(observer);
99 } 134 }
100 135
136 void ErrorConsole::OnPrefChanged() {
137 bool developer_mode =
138 profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode);
139
140 if (developer_mode && !enabled_)
141 Enable(ExtensionSystem::Get(profile_)->extension_service());
142 else if (!developer_mode && enabled_)
143 Disable();
144 }
145
146 void ErrorConsole::Enable(ExtensionService* extension_service) {
147 enabled_ = true;
148
149 notification_registrar_.Add(
150 this,
151 chrome::NOTIFICATION_PROFILE_DESTROYED,
152 content::NotificationService::AllBrowserContextsAndSources());
153 notification_registrar_.Add(
154 this,
155 chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
156 content::Source<Profile>(profile_));
157 notification_registrar_.Add(
158 this,
159 chrome::NOTIFICATION_EXTENSION_INSTALLED,
160 content::Source<Profile>(profile_));
161
162 if (extension_service) {
163 // Get manifest errors for extensions already installed.
164 const ExtensionSet* extensions = extension_service->extensions();
165 for (ExtensionSet::const_iterator iter = extensions->begin();
166 iter != extensions->end(); ++iter) {
167 AddManifestErrorsForExtension(iter->get());
168 }
169 }
170 }
171
172 void ErrorConsole::Disable() {
173 notification_registrar_.RemoveAll();
174 RemoveAllErrors();
175 enabled_ = false;
176 }
177
178 void ErrorConsole::AddManifestErrorsForExtension(const Extension* extension) {
179 const std::vector<InstallWarning>& warnings =
180 extension->install_warnings();
181 for (std::vector<InstallWarning>::const_iterator iter = warnings.begin();
182 iter != warnings.end(); ++iter) {
183 ReportError(scoped_ptr<const ExtensionError>(new ManifestParsingError(
Yoyo Zhou 2013/08/16 00:17:25 Seeing this makes me wonder whether it's right to
Devlin 2013/08/16 23:56:54 I've been wondering that as well... How about a g
Yoyo Zhou 2013/08/19 20:39:46 ManifestError seems fine. If we want to have other
Devlin 2013/08/19 21:42:39 Done.
184 extension->id(),
185 base::UTF8ToUTF16(iter->message),
186 base::UTF8ToUTF16(iter->key),
187 base::UTF8ToUTF16(iter->specific))));
188 }
189 }
190
101 void ErrorConsole::RemoveIncognitoErrors() { 191 void ErrorConsole::RemoveIncognitoErrors() {
102 for (ErrorMap::iterator iter = errors_.begin(); 192 for (ErrorMap::iterator iter = errors_.begin();
103 iter != errors_.end(); ++iter) { 193 iter != errors_.end(); ++iter) {
104 DeleteIncognitoErrorsFromList(&(iter->second)); 194 DeleteIncognitoErrorsFromList(&(iter->second));
105 } 195 }
106 } 196 }
107 197
108 void ErrorConsole::RemoveErrorsForExtension(const std::string& extension_id) { 198 void ErrorConsole::RemoveErrorsForExtension(const std::string& extension_id) {
109 ErrorMap::iterator iter = errors_.find(extension_id); 199 ErrorMap::iterator iter = errors_.find(extension_id);
110 if (iter != errors_.end()) { 200 if (iter != errors_.end()) {
(...skipping 19 matching lines...) Expand all
130 if (profile->IsOffTheRecord() && profile_->IsSameProfile(profile)) 220 if (profile->IsOffTheRecord() && profile_->IsSameProfile(profile))
131 RemoveIncognitoErrors(); 221 RemoveIncognitoErrors();
132 break; 222 break;
133 } 223 }
134 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: 224 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
135 // No need to check the profile here, since we registered to only receive 225 // No need to check the profile here, since we registered to only receive
136 // notifications from our own. 226 // notifications from our own.
137 RemoveErrorsForExtension( 227 RemoveErrorsForExtension(
138 content::Details<Extension>(details).ptr()->id()); 228 content::Details<Extension>(details).ptr()->id());
139 break; 229 break;
230 case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
231 const InstalledExtensionInfo* info =
232 content::Details<InstalledExtensionInfo>(details).ptr();
233
234 // We don't want to have manifest errors from previous installs. We want
235 // to keep runtime errors, though, because extensions are reloaded on a
236 // refresh of chrome:extensions, and we don't want to wipe our history
Yoyo Zhou 2013/08/16 00:17:25 Does this notification get sent when unpacked exte
Devlin 2013/08/16 23:56:54 Yep, it does. Which means that any time the page w
237 // whenever that happens.
238 ErrorMap::iterator iter = errors_.find(info->extension->id());
239 if (iter != errors_.end()) {
240 DeleteErrorsOfTypeFromList(&(iter->second),
241 ExtensionError::MANIFEST_PARSING_ERROR);
242 }
243
244 AddManifestErrorsForExtension(info->extension);
245 break;
246 }
140 default: 247 default:
141 NOTREACHED(); 248 NOTREACHED();
142 } 249 }
143 } 250 }
144 251
145 } // namespace extensions 252 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698