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

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

Issue 10407105: Improve error messaging of webRequest API in case of conflicts (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Store ExtensionWarnings as values in set rather than pointers Created 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/extension_warning_set.h" 5 #include "chrome/browser/extensions/extension_warning_set.h"
6 6
7 #include "base/utf_string_conversions.h"
7 #include "chrome/browser/browser_process.h" 8 #include "chrome/browser/browser_process.h"
8 #include "chrome/browser/extensions/extension_global_error_badge.h" 9 #include "chrome/browser/extensions/extension_global_error_badge.h"
9 #include "chrome/browser/extensions/extension_service.h" 10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/extension_system.h"
10 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/profiles/profile_manager.h" 13 #include "chrome/browser/profiles/profile_manager.h"
12 #include "chrome/browser/ui/global_error/global_error_service.h" 14 #include "chrome/browser/ui/global_error/global_error_service.h"
13 #include "chrome/browser/ui/global_error/global_error_service_factory.h" 15 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
14 #include "chrome/common/chrome_notification_types.h" 16 #include "chrome/common/chrome_notification_types.h"
17 #include "chrome/common/extensions/extension.h"
18 #include "chrome/common/extensions/extension_set.h"
15 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/notification_service.h" 20 #include "content/public/browser/notification_service.h"
17 #include "grit/chromium_strings.h" 21 #include "grit/chromium_strings.h"
18 #include "grit/generated_resources.h" 22 #include "grit/generated_resources.h"
23 #include "net/base/escape.h"
19 #include "ui/base/l10n/l10n_util.h" 24 #include "ui/base/l10n/l10n_util.h"
20 25
21 using content::BrowserThread; 26 using content::BrowserThread;
22 27
23 // This class is used to represent warnings if extensions misbehave. 28 namespace {
24 class ExtensionWarning { 29 // Prefix for message parameters indicating that the parameter needs to
25 public: 30 // be translated from an extension id to the extension name.
26 // Default constructor for storing ExtensionServiceWarning in STL containers 31 const char kTranslate[] = "TO_TRANSLATE:";
27 // do not use. 32 const size_t kMaxNumberOfParameters = 4;
28 ExtensionWarning(); 33 }
29 34
30 // Constructs a warning of type |type| for extension |extension_id|. This 35 namespace extensions {
31 // could be for example the fact that an extension conflicted with others. 36
32 ExtensionWarning(ExtensionWarningSet::WarningType type, 37 //
33 const std::string& extension_id); 38 // ExtensionWarning
34 39 //
35 ~ExtensionWarning();
36
37 // Returns the specific warning type.
38 ExtensionWarningSet::WarningType warning_type() const { return type_; }
39
40 // Returns the id of the extension for which this warning is valid.
41 const std::string& extension_id() const { return extension_id_; }
42
43 private:
44 ExtensionWarningSet::WarningType type_;
45 std::string extension_id_;
46
47 // Allow implicit copy and assign operator.
48 };
49
50 ExtensionWarning::ExtensionWarning() : type_(ExtensionWarningSet::kInvalid) {
51 }
52 40
53 ExtensionWarning::ExtensionWarning( 41 ExtensionWarning::ExtensionWarning(
54 ExtensionWarningSet::WarningType type, 42 WarningType type,
55 const std::string& extension_id) 43 const std::string& extension_id,
56 : type_(type), extension_id_(extension_id) { 44 int message_id,
45 const std::vector<std::string>& message_parameters)
46 : type_(type),
47 extension_id_(extension_id),
48 message_id_(message_id),
49 message_parameters_(message_parameters) {
57 // These are invalid here because they do not have corresponding warning 50 // These are invalid here because they do not have corresponding warning
58 // messages in the UI. 51 // messages in the UI.
59 CHECK(type != ExtensionWarningSet::kInvalid); 52 CHECK_NE(type, kInvalid);
60 CHECK(type != ExtensionWarningSet::kMaxWarningType); 53 CHECK_NE(type, kMaxWarningType);
61 } 54 CHECK_LE(message_parameters.size(), kMaxNumberOfParameters);
55 }
56
57 ExtensionWarning::ExtensionWarning(const ExtensionWarning& other)
58 : type_(other.type_),
59 extension_id_(other.extension_id_),
60 message_id_(other.message_id_),
61 message_parameters_(other.message_parameters_) {}
62 62
63 ExtensionWarning::~ExtensionWarning() { 63 ExtensionWarning::~ExtensionWarning() {
64 } 64 }
65 65
66 void ExtensionWarning::operator=(const ExtensionWarning& other) {
67 type_ = other.type_;
68 extension_id_ = other.extension_id_;
69 message_id_ = other.message_id_;
70 message_parameters_ = other.message_parameters_;
71 }
72
73 // static
74 ExtensionWarning ExtensionWarning::CreateNetworkDelayWarning(
75 const std::string& extension_id) {
76 std::vector<std::string> message_parameters;
77 message_parameters.push_back(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
78 return ExtensionWarning(
79 kNetworkDelay,
80 extension_id,
81 IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
82 message_parameters);
83 }
84
85 // static
86 ExtensionWarning ExtensionWarning::CreateNetworkConflictWarning(
87 const std::string& extension_id) {
88 std::vector<std::string> message_parameters;
89 return ExtensionWarning(
90 kNetworkConflict,
91 extension_id,
92 IDS_EXTENSION_WARNINGS_NETWORK_CONFLICT,
93 message_parameters);
94 }
95
96 // static
97 ExtensionWarning ExtensionWarning::CreateRedirectConflictWarning(
98 const std::string& extension_id,
99 const std::string& winning_extension_id,
100 const GURL& attempted_redirect_url,
101 const GURL& winning_redirect_url) {
102 std::vector<std::string> message_parameters;
103 message_parameters.push_back(attempted_redirect_url.spec());
104 message_parameters.push_back(kTranslate + winning_extension_id);
105 message_parameters.push_back(winning_redirect_url.spec());
106 return ExtensionWarning(
107 kRedirectConflict,
108 extension_id,
109 IDS_EXTENSION_WARNINGS_REDIRECT_CONFLICT,
110 message_parameters);
111 }
112
113 // static
114 ExtensionWarning ExtensionWarning::CreateRequestHeaderConflictWarning(
115 const std::string& extension_id,
116 const std::string& winning_extension_id,
117 const std::string& conflicting_header) {
118 std::vector<std::string> message_parameters;
119 message_parameters.push_back(conflicting_header);
120 message_parameters.push_back(kTranslate + winning_extension_id);
121 return ExtensionWarning(
122 kNetworkConflict,
123 extension_id,
124 IDS_EXTENSION_WARNINGS_REQUEST_HEADER_CONFLICT,
125 message_parameters);
126 }
127
128 // static
129 ExtensionWarning ExtensionWarning::CreateResponseHeaderConflictWarning(
130 const std::string& extension_id,
131 const std::string& winning_extension_id,
132 const std::string& conflicting_header) {
133 std::vector<std::string> message_parameters;
134 message_parameters.push_back(conflicting_header);
135 message_parameters.push_back(kTranslate + winning_extension_id);
136 return ExtensionWarning(
137 kNetworkConflict,
138 extension_id,
139 IDS_EXTENSION_WARNINGS_RESPONSE_HEADER_CONFLICT,
140 message_parameters);
141 }
142
143 // static
144 ExtensionWarning ExtensionWarning::CreateCredentialsConflictWarning(
145 const std::string& extension_id,
146 const std::string& winning_extension_id) {
147 std::vector<std::string> message_parameters;
148 message_parameters.push_back(kTranslate + winning_extension_id);
149 return ExtensionWarning(
150 kNetworkConflict,
151 extension_id,
152 IDS_EXTENSION_WARNINGS_CREDENTIALS_CONFLICT,
153 message_parameters);
154 }
155
156 // static
157 ExtensionWarning ExtensionWarning::CreateRepeatedCacheFlushesWarning(
158 const std::string& extension_id) {
159 std::vector<std::string> message_parameters;
160 message_parameters.push_back(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
161 return ExtensionWarning(
162 kRepeatedCacheFlushes,
163 extension_id,
164 IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
165 message_parameters);
166 }
167
168 const std::string ExtensionWarning::GetMessage(
169 const ExtensionSet* extensions) const {
170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
171
172 // These parameters may be unsafe (URLs and Extension names) and need
173 // to be HTML-escaped before being embedded in the UI. Also extension IDs
174 // are translated to full extension names.
175 std::vector<string16> final_parameters;
176 for (size_t i = 0; i < message_parameters_.size(); ++i) {
177 std::string message = message_parameters_[i];
178 if (StartsWithASCII(message, kTranslate, true)) {
179 std::string extension_id = message.substr(sizeof(kTranslate) - 1);
180 const extensions::Extension* extension =
181 extensions->GetByID(extension_id);
182 message = extension ? extension->name() : extension_id;
183 }
184 final_parameters.push_back(UTF8ToUTF16(net::EscapeForHTML(message)));
185 }
186
187 COMPILE_ASSERT(kMaxNumberOfParameters == 4u, YouNeedToAddMoreCaseStatements);
188 switch (final_parameters.size()) {
189 case 0:
190 return l10n_util::GetStringUTF8(message_id_);
191 case 1:
192 return l10n_util::GetStringFUTF8(message_id_, final_parameters[0]);
193 case 2:
194 return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
195 final_parameters[1]);
196 case 3:
197 return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
198 final_parameters[1], final_parameters[2]);
199 case 4:
200 return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
201 final_parameters[1], final_parameters[2], final_parameters[3]);
202 default:
203 NOTREACHED();
204 return std::string();
205 }
206 }
207
66 bool operator<(const ExtensionWarning& a, const ExtensionWarning& b) { 208 bool operator<(const ExtensionWarning& a, const ExtensionWarning& b) {
67 if (a.warning_type() == b.warning_type()) 209 if (a.extension_id() != b.extension_id())
68 return a.extension_id() < b.extension_id(); 210 return a.extension_id() < b.extension_id();
69 return a.warning_type() < b.warning_type(); 211 return a.warning_type() < b.warning_type();
70 } 212 }
71 213
72 // Static 214 //
73 string16 ExtensionWarningSet::GetLocalizedWarning( 215 // ExtensionWarningService
74 ExtensionWarningSet::WarningType warning_type) { 216 //
75 switch (warning_type) { 217
76 case kInvalid: 218 ExtensionWarningService::ExtensionWarningService(Profile* profile)
77 case kMaxWarningType: 219 : profile_(profile) {
78 NOTREACHED(); 220 DCHECK(CalledOnValidThread());
79 return string16(); 221 }
80 case kNetworkDelay: 222
81 return l10n_util::GetStringFUTF16( 223 ExtensionWarningService::~ExtensionWarningService() {}
82 IDS_EXTENSION_WARNINGS_NETWORK_DELAY, 224
83 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 225 void ExtensionWarningService::ClearWarnings(
84 case kNetworkConflict: 226 const std::set<ExtensionWarning::WarningType>& types) {
85 return l10n_util::GetStringUTF16(IDS_EXTENSION_WARNINGS_NETWORK_CONFLICT); 227 DCHECK(CalledOnValidThread());
86 case kRepeatedCacheFlushes:
87 return l10n_util::GetStringFUTF16(
88 IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
89 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
90 }
91 NOTREACHED(); // Switch statement has no default branch.
92 return string16();
93 }
94
95 ExtensionWarningSet::ExtensionWarningSet(Profile* profile) : profile_(profile) {
96 }
97
98 ExtensionWarningSet::~ExtensionWarningSet() {
99 }
100
101 void ExtensionWarningSet::SetWarning(ExtensionWarningSet::WarningType type,
102 const std::string& extension_id) {
103 ExtensionWarning warning(type, extension_id);
104 bool inserted = warnings_.insert(warning).second;
105 if (inserted) {
106 NotifyWarningsChanged();
107 UpdateWarningBadge();
108 }
109 }
110
111 void ExtensionWarningSet::ClearWarnings(
112 const std::set<ExtensionWarningSet::WarningType>& types) {
113 bool deleted_anything = false; 228 bool deleted_anything = false;
114 for (iterator i = warnings_.begin(); i != warnings_.end();) { 229 for (iterator i = warnings_.begin(); i != warnings_.end();) {
115 if (types.find(i->warning_type()) != types.end()) { 230 if (types.find(i->warning_type()) != types.end()) {
116 deleted_anything = true; 231 deleted_anything = true;
117 warnings_.erase(i++); 232 warnings_.erase(i++);
118 } else { 233 } else {
119 ++i; 234 ++i;
120 } 235 }
121 } 236 }
122 237
123 if (deleted_anything) { 238 if (deleted_anything) {
124 NotifyWarningsChanged(); 239 NotifyWarningsChanged();
125 UpdateWarningBadge(); 240 UpdateWarningBadge();
126 } 241 }
127 } 242 }
128 243
129 void ExtensionWarningSet::GetWarningsAffectingExtension( 244 void ExtensionWarningService::GetWarningTypesAffectingExtension(
130 const std::string& extension_id, 245 const std::string& extension_id,
131 std::set<ExtensionWarningSet::WarningType>* result) const { 246 std::set<ExtensionWarning::WarningType>* result) const {
247 DCHECK(CalledOnValidThread());
132 result->clear(); 248 result->clear();
133 for (const_iterator i = warnings_.begin(); i != warnings_.end(); ++i) { 249 for (const_iterator i = warnings_.begin(); i != warnings_.end(); ++i) {
134 if (i->extension_id() == extension_id) 250 if (i->extension_id() == extension_id)
135 result->insert(i->warning_type()); 251 result->insert(i->warning_type());
136 } 252 }
137 } 253 }
138 254
255 void ExtensionWarningService::GetWarningMessagesForExtension(
256 const std::string& extension_id,
257 std::vector<std::string>* result) const {
258 DCHECK(CalledOnValidThread());
259 result->clear();
260
261 const ExtensionService* extension_service =
262 ExtensionSystem::Get(profile_)->extension_service();
263
264 for (const_iterator i = warnings_.begin(); i != warnings_.end(); ++i) {
265 if (i->extension_id() == extension_id)
266 result->push_back(i->GetMessage(extension_service->extensions()));
267 }
268 }
269
270 void ExtensionWarningService::AddWarnings(
271 const ExtensionWarningSet& warnings) {
272 DCHECK(CalledOnValidThread());
273 size_t old_size = warnings_.size();
274
275 warnings_.insert(warnings.begin(), warnings.end());
276
277 if (old_size != warnings_.size()) {
278 NotifyWarningsChanged();
279 UpdateWarningBadge();
280 }
281 }
282
139 // static 283 // static
140 void ExtensionWarningSet::NotifyWarningsOnUI( 284 void ExtensionWarningService::NotifyWarningsOnUI(
141 void* profile_id, 285 void* profile_id,
142 std::set<std::string> extension_ids, 286 ExtensionWarningSet warnings) {
143 WarningType warning_type) { 287 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
144 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
145 Profile* profile = reinterpret_cast<Profile*>(profile_id); 288 Profile* profile = reinterpret_cast<Profile*>(profile_id);
146 if (!profile || 289 if (!profile ||
147 !g_browser_process->profile_manager() || 290 !g_browser_process->profile_manager() ||
148 !g_browser_process->profile_manager()->IsValidProfile(profile)) { 291 !g_browser_process->profile_manager()->IsValidProfile(profile)) {
149 return; 292 return;
150 } 293 }
151 294
152 ExtensionWarningSet* warnings = 295 extensions::ExtensionWarningService* warning_service =
153 profile->GetExtensionService()->extension_warnings(); 296 extensions::ExtensionSystem::Get(profile)->warning_service();
154 297
155 for (std::set<std::string>::const_iterator i = extension_ids.begin(); 298 warning_service->AddWarnings(warnings);
156 i != extension_ids.end(); ++i) {
157 warnings->SetWarning(warning_type, *i);
158 }
159 } 299 }
160 300
161 void ExtensionWarningSet::SuppressBadgeForCurrentWarnings() { 301 void ExtensionWarningService::SuppressBadgeForCurrentWarnings() {
302 DCHECK(CalledOnValidThread());
162 badge_suppressions_.insert(warnings_.begin(), warnings_.end()); 303 badge_suppressions_.insert(warnings_.begin(), warnings_.end());
163 UpdateWarningBadge(); 304 UpdateWarningBadge();
164 } 305 }
165 306
166 void ExtensionWarningSet::NotifyWarningsChanged() { 307 void ExtensionWarningService::NotifyWarningsChanged() {
308 DCHECK(CalledOnValidThread());
167 content::NotificationService::current()->Notify( 309 content::NotificationService::current()->Notify(
168 chrome::NOTIFICATION_EXTENSION_WARNING_CHANGED, 310 chrome::NOTIFICATION_EXTENSION_WARNING_CHANGED,
169 content::Source<Profile>(profile_), 311 content::Source<Profile>(profile_),
170 content::NotificationService::NoDetails()); 312 content::NotificationService::NoDetails());
171 } 313 }
172 314
173 void ExtensionWarningSet::UpdateWarningBadge() { 315 void ExtensionWarningService::UpdateWarningBadge() {
316 DCHECK(CalledOnValidThread());
174 // We need a badge if a warning exists that has not been suppressed. 317 // We need a badge if a warning exists that has not been suppressed.
175 bool need_warning_badge = false; 318 bool need_warning_badge = false;
176 for (const_iterator i = warnings_.begin(); i != warnings_.end(); ++i) { 319 for (const_iterator i = warnings_.begin(); i != warnings_.end(); ++i) {
177 if (badge_suppressions_.find(*i) == badge_suppressions_.end()) { 320 if (badge_suppressions_.find(*i) == badge_suppressions_.end()) {
178 need_warning_badge = true; 321 need_warning_badge = true;
179 break; 322 break;
180 } 323 }
181 } 324 }
182 325
183 GlobalErrorService* service = 326 GlobalErrorService* service =
184 GlobalErrorServiceFactory::GetForProfile(profile_); 327 GlobalErrorServiceFactory::GetForProfile(profile_);
185 GlobalError* error = service->GetGlobalErrorByMenuItemCommandID( 328 GlobalError* error = service->GetGlobalErrorByMenuItemCommandID(
186 ExtensionGlobalErrorBadge::GetMenuItemCommandID()); 329 ExtensionGlobalErrorBadge::GetMenuItemCommandID());
187 330
188 // Activate or hide the warning badge in case the current state is incorrect. 331 // Activate or hide the warning badge in case the current state is incorrect.
189 if (error && !need_warning_badge) { 332 if (error && !need_warning_badge) {
190 service->RemoveGlobalError(error); 333 service->RemoveGlobalError(error);
191 delete error; 334 delete error;
192 } else if (!error && need_warning_badge) { 335 } else if (!error && need_warning_badge) {
193 service->AddGlobalError(new ExtensionGlobalErrorBadge); 336 service->AddGlobalError(new ExtensionGlobalErrorBadge);
194 } 337 }
195 } 338 }
339
340 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698