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

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

Powered by Google App Engine
This is Rietveld 408576698