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

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: Requested UI Changes 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> error) {
68 DCHECK(thread_checker_.CalledOnValidThread()); 91 DCHECK(thread_checker_.CalledOnValidThread());
69 92
70 const ExtensionError* error = scoped_error.release(); 93 if (!enabled_ || !Extension::IdIsValid(error->extension_id()))
71 // If there are too many errors for an extension already, limit ourselves to 94 return;
72 // the most recent ones. 95
73 ErrorList* error_list = &errors_[error->extension_id()]; 96 // This will be assigned when we place the error in the list, releasing the
74 if (error_list->size() >= kMaxErrorsPerExtension) { 97 // scoped_ptr.
75 delete error_list->front(); 98 const ExtensionError* weak_error = NULL;
76 error_list->pop_front(); 99 ErrorList* extension_errors = &errors_[error->extension_id()];
100
101 // First, check if it's a duplicate.
102 for (size_t i = 0; i < extension_errors->size(); ++i) {
103 // If we find a duplicate error, replace the error with the new version.
104 // This can be useful for runtime errors, where we can link to the latest
105 // context, inspectable view, etc.
106 if (error->IsEqual(extension_errors->at(i))) {
107 delete extension_errors->at(i);
108 extension_errors->at(i) = error.release();
109 weak_error = extension_errors->at(i);
110 break;
111 }
77 } 112 }
78 error_list->push_back(error);
79 113
80 FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(error)); 114 // If we didn't replace a previous error, then we add the error to the end of
115 // the list.
116 if (!weak_error) {
117 // If there are too many errors for an extension already, limit ourselves to
118 // the most recent ones.
119 if (extension_errors->size() >= kMaxErrorsPerExtension) {
120 delete extension_errors->front();
121 extension_errors->pop_front();
122 }
123 extension_errors->push_back(error.release());
124 weak_error = extension_errors->back();
125 }
126
127 FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(weak_error));
81 } 128 }
82 129
83 const ErrorConsole::ErrorList& ErrorConsole::GetErrorsForExtension( 130 const ErrorConsole::ErrorList& ErrorConsole::GetErrorsForExtension(
84 const std::string& extension_id) const { 131 const std::string& extension_id) const {
85 ErrorMap::const_iterator iter = errors_.find(extension_id); 132 ErrorMap::const_iterator iter = errors_.find(extension_id);
86 if (iter != errors_.end()) 133 if (iter != errors_.end())
87 return iter->second; 134 return iter->second;
88 return g_empty_error_list.Get(); 135 return g_empty_error_list.Get();
89 } 136 }
90 137
91 void ErrorConsole::AddObserver(Observer* observer) { 138 void ErrorConsole::AddObserver(Observer* observer) {
92 DCHECK(thread_checker_.CalledOnValidThread()); 139 DCHECK(thread_checker_.CalledOnValidThread());
93 observers_.AddObserver(observer); 140 observers_.AddObserver(observer);
94 } 141 }
95 142
96 void ErrorConsole::RemoveObserver(Observer* observer) { 143 void ErrorConsole::RemoveObserver(Observer* observer) {
97 DCHECK(thread_checker_.CalledOnValidThread()); 144 DCHECK(thread_checker_.CalledOnValidThread());
98 observers_.RemoveObserver(observer); 145 observers_.RemoveObserver(observer);
99 } 146 }
100 147
148 void ErrorConsole::OnPrefChanged() {
149 bool developer_mode =
150 profile_->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode);
151
152 if (developer_mode && !enabled_)
153 Enable(ExtensionSystem::Get(profile_)->extension_service());
154 else if (!developer_mode && enabled_)
155 Disable();
156 }
157
158 void ErrorConsole::Enable(ExtensionService* extension_service) {
159 enabled_ = true;
160
161 notification_registrar_.Add(
162 this,
163 chrome::NOTIFICATION_PROFILE_DESTROYED,
164 content::NotificationService::AllBrowserContextsAndSources());
165 notification_registrar_.Add(
166 this,
167 chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
168 content::Source<Profile>(profile_));
169 notification_registrar_.Add(
170 this,
171 chrome::NOTIFICATION_EXTENSION_INSTALLED,
172 content::Source<Profile>(profile_));
173
174 if (extension_service) {
175 // Get manifest errors for extensions already installed.
176 const ExtensionSet* extensions = extension_service->extensions();
177 for (ExtensionSet::const_iterator iter = extensions->begin();
178 iter != extensions->end(); ++iter) {
179 AddManifestErrorsForExtension(iter->get());
180 }
181 }
182 }
183
184 void ErrorConsole::Disable() {
185 notification_registrar_.RemoveAll();
186 RemoveAllErrors();
187 enabled_ = false;
188 }
189
190 void ErrorConsole::AddManifestErrorsForExtension(const Extension* extension) {
191 const std::vector<InstallWarning>& warnings =
192 extension->install_warnings();
193 for (std::vector<InstallWarning>::const_iterator iter = warnings.begin();
194 iter != warnings.end(); ++iter) {
195 ReportError(scoped_ptr<const ExtensionError>(new ManifestError(
196 extension->id(),
197 base::UTF8ToUTF16(iter->message),
198 base::UTF8ToUTF16(iter->key),
199 base::UTF8ToUTF16(iter->specific))));
200 }
201 }
202
101 void ErrorConsole::RemoveIncognitoErrors() { 203 void ErrorConsole::RemoveIncognitoErrors() {
102 for (ErrorMap::iterator iter = errors_.begin(); 204 for (ErrorMap::iterator iter = errors_.begin();
103 iter != errors_.end(); ++iter) { 205 iter != errors_.end(); ++iter) {
104 DeleteIncognitoErrorsFromList(&(iter->second)); 206 DeleteIncognitoErrorsFromList(&(iter->second));
105 } 207 }
106 } 208 }
107 209
108 void ErrorConsole::RemoveErrorsForExtension(const std::string& extension_id) { 210 void ErrorConsole::RemoveErrorsForExtension(const std::string& extension_id) {
109 ErrorMap::iterator iter = errors_.find(extension_id); 211 ErrorMap::iterator iter = errors_.find(extension_id);
110 if (iter != errors_.end()) { 212 if (iter != errors_.end()) {
(...skipping 19 matching lines...) Expand all
130 if (profile->IsOffTheRecord() && profile_->IsSameProfile(profile)) 232 if (profile->IsOffTheRecord() && profile_->IsSameProfile(profile))
131 RemoveIncognitoErrors(); 233 RemoveIncognitoErrors();
132 break; 234 break;
133 } 235 }
134 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: 236 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
135 // No need to check the profile here, since we registered to only receive 237 // No need to check the profile here, since we registered to only receive
136 // notifications from our own. 238 // notifications from our own.
137 RemoveErrorsForExtension( 239 RemoveErrorsForExtension(
138 content::Details<Extension>(details).ptr()->id()); 240 content::Details<Extension>(details).ptr()->id());
139 break; 241 break;
242 case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
243 const InstalledExtensionInfo* info =
244 content::Details<InstalledExtensionInfo>(details).ptr();
245
246 // We don't want to have manifest errors from previous installs. We want
247 // to keep runtime errors, though, because extensions are reloaded on a
248 // refresh of chrome:extensions, and we don't want to wipe our history
249 // whenever that happens.
250 ErrorMap::iterator iter = errors_.find(info->extension->id());
251 if (iter != errors_.end()) {
252 DeleteErrorsOfTypeFromList(&(iter->second),
253 ExtensionError::MANIFEST_ERROR);
254 }
255
256 AddManifestErrorsForExtension(info->extension);
257 break;
258 }
140 default: 259 default:
141 NOTREACHED(); 260 NOTREACHED();
142 } 261 }
143 } 262 }
144 263
145 } // namespace extensions 264 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698