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

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: Addressed Evan's comments Created 8 years, 1 month 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_service.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/profiles/profile_manager.h"
12 #include "chrome/browser/ui/global_error/global_error_service.h"
13 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
14 #include "chrome/common/chrome_notification_types.h" 9 #include "chrome/common/chrome_notification_types.h"
10 #include "chrome/common/extensions/extension.h"
11 #include "chrome/common/extensions/extension_set.h"
15 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/notification_service.h"
17 #include "grit/chromium_strings.h" 13 #include "grit/chromium_strings.h"
18 #include "grit/generated_resources.h" 14 #include "grit/generated_resources.h"
15 #include "net/base/escape.h"
19 #include "ui/base/l10n/l10n_util.h" 16 #include "ui/base/l10n/l10n_util.h"
20 17
21 using content::BrowserThread; 18 using content::BrowserThread;
22 19
23 // This class is used to represent warnings if extensions misbehave. 20 namespace {
24 class ExtensionWarning { 21 // Prefix for message parameters indicating that the parameter needs to
25 public: 22 // be translated from an extension id to the extension name.
26 // Default constructor for storing ExtensionServiceWarning in STL containers 23 const char kTranslate[] = "TO_TRANSLATE:";
27 // do not use. 24 const size_t kMaxNumberOfParameters = 4;
28 ExtensionWarning(); 25 }
29 26
30 // Constructs a warning of type |type| for extension |extension_id|. This 27 namespace extensions {
31 // could be for example the fact that an extension conflicted with others. 28
32 ExtensionWarning(ExtensionWarningSet::WarningType type, 29 //
33 const std::string& extension_id); 30 // ExtensionWarning
34 31 //
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 32
53 ExtensionWarning::ExtensionWarning( 33 ExtensionWarning::ExtensionWarning(
54 ExtensionWarningSet::WarningType type, 34 WarningType type,
55 const std::string& extension_id) 35 const std::string& extension_id,
56 : type_(type), extension_id_(extension_id) { 36 int message_id,
37 const std::vector<std::string>& message_parameters)
38 : type_(type),
39 extension_id_(extension_id),
40 message_id_(message_id),
41 message_parameters_(message_parameters) {
57 // These are invalid here because they do not have corresponding warning 42 // These are invalid here because they do not have corresponding warning
58 // messages in the UI. 43 // messages in the UI.
59 CHECK(type != ExtensionWarningSet::kInvalid); 44 CHECK_NE(type, kInvalid);
60 CHECK(type != ExtensionWarningSet::kMaxWarningType); 45 CHECK_NE(type, kMaxWarningType);
61 } 46 CHECK_LE(message_parameters.size(), kMaxNumberOfParameters);
47 }
48
49 ExtensionWarning::ExtensionWarning(const ExtensionWarning& other)
50 : type_(other.type_),
51 extension_id_(other.extension_id_),
52 message_id_(other.message_id_),
53 message_parameters_(other.message_parameters_) {}
62 54
63 ExtensionWarning::~ExtensionWarning() { 55 ExtensionWarning::~ExtensionWarning() {
64 } 56 }
65 57
58 ExtensionWarning& ExtensionWarning::operator=(const ExtensionWarning& other) {
59 type_ = other.type_;
60 extension_id_ = other.extension_id_;
61 message_id_ = other.message_id_;
62 message_parameters_ = other.message_parameters_;
63 return *this;
64 }
65
66 // static
67 ExtensionWarning ExtensionWarning::CreateNetworkDelayWarning(
68 const std::string& extension_id) {
69 std::vector<std::string> message_parameters;
70 message_parameters.push_back(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
71 return ExtensionWarning(
72 kNetworkDelay,
73 extension_id,
74 IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
75 message_parameters);
76 }
77
78 // static
79 ExtensionWarning ExtensionWarning::CreateNetworkConflictWarning(
80 const std::string& extension_id) {
81 std::vector<std::string> message_parameters;
82 return ExtensionWarning(
83 kNetworkConflict,
84 extension_id,
85 IDS_EXTENSION_WARNINGS_NETWORK_CONFLICT,
86 message_parameters);
87 }
88
89 // static
90 ExtensionWarning ExtensionWarning::CreateRedirectConflictWarning(
91 const std::string& extension_id,
92 const std::string& winning_extension_id,
93 const GURL& attempted_redirect_url,
94 const GURL& winning_redirect_url) {
95 std::vector<std::string> message_parameters;
96 message_parameters.push_back(attempted_redirect_url.spec());
97 message_parameters.push_back(kTranslate + winning_extension_id);
98 message_parameters.push_back(winning_redirect_url.spec());
99 return ExtensionWarning(
100 kRedirectConflict,
101 extension_id,
102 IDS_EXTENSION_WARNINGS_REDIRECT_CONFLICT,
103 message_parameters);
104 }
105
106 // static
107 ExtensionWarning ExtensionWarning::CreateRequestHeaderConflictWarning(
108 const std::string& extension_id,
109 const std::string& winning_extension_id,
110 const std::string& conflicting_header) {
111 std::vector<std::string> message_parameters;
112 message_parameters.push_back(conflicting_header);
113 message_parameters.push_back(kTranslate + winning_extension_id);
114 return ExtensionWarning(
115 kNetworkConflict,
116 extension_id,
117 IDS_EXTENSION_WARNINGS_REQUEST_HEADER_CONFLICT,
118 message_parameters);
119 }
120
121 // static
122 ExtensionWarning ExtensionWarning::CreateResponseHeaderConflictWarning(
123 const std::string& extension_id,
124 const std::string& winning_extension_id,
125 const std::string& conflicting_header) {
126 std::vector<std::string> message_parameters;
127 message_parameters.push_back(conflicting_header);
128 message_parameters.push_back(kTranslate + winning_extension_id);
129 return ExtensionWarning(
130 kNetworkConflict,
131 extension_id,
132 IDS_EXTENSION_WARNINGS_RESPONSE_HEADER_CONFLICT,
133 message_parameters);
134 }
135
136 // static
137 ExtensionWarning ExtensionWarning::CreateCredentialsConflictWarning(
138 const std::string& extension_id,
139 const std::string& winning_extension_id) {
140 std::vector<std::string> message_parameters;
141 message_parameters.push_back(kTranslate + winning_extension_id);
142 return ExtensionWarning(
143 kNetworkConflict,
144 extension_id,
145 IDS_EXTENSION_WARNINGS_CREDENTIALS_CONFLICT,
146 message_parameters);
147 }
148
149 // static
150 ExtensionWarning ExtensionWarning::CreateRepeatedCacheFlushesWarning(
151 const std::string& extension_id) {
152 std::vector<std::string> message_parameters;
153 message_parameters.push_back(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
154 return ExtensionWarning(
155 kRepeatedCacheFlushes,
156 extension_id,
157 IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
158 message_parameters);
159 }
160
161 std::string ExtensionWarning::GetLocalizedMessage(
162 const ExtensionSet* extensions) const {
163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
164
165 // These parameters may be unsafe (URLs and Extension names) and need
166 // to be HTML-escaped before being embedded in the UI. Also extension IDs
167 // are translated to full extension names.
168 std::vector<string16> final_parameters;
169 for (size_t i = 0; i < message_parameters_.size(); ++i) {
170 std::string message = message_parameters_[i];
171 if (StartsWithASCII(message, kTranslate, true)) {
172 std::string extension_id = message.substr(sizeof(kTranslate) - 1);
173 const extensions::Extension* extension =
174 extensions->GetByID(extension_id);
175 message = extension ? extension->name() : extension_id;
176 }
177 final_parameters.push_back(UTF8ToUTF16(net::EscapeForHTML(message)));
178 }
179
180 COMPILE_ASSERT(kMaxNumberOfParameters == 4u, YouNeedToAddMoreCaseStatements);
181 switch (final_parameters.size()) {
182 case 0:
183 return l10n_util::GetStringUTF8(message_id_);
184 case 1:
185 return l10n_util::GetStringFUTF8(message_id_, final_parameters[0]);
186 case 2:
187 return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
188 final_parameters[1]);
189 case 3:
190 return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
191 final_parameters[1], final_parameters[2]);
192 case 4:
193 return l10n_util::GetStringFUTF8(message_id_, final_parameters[0],
194 final_parameters[1], final_parameters[2], final_parameters[3]);
195 default:
196 NOTREACHED();
197 return std::string();
198 }
199 }
200
66 bool operator<(const ExtensionWarning& a, const ExtensionWarning& b) { 201 bool operator<(const ExtensionWarning& a, const ExtensionWarning& b) {
67 if (a.warning_type() == b.warning_type()) 202 if (a.extension_id() != b.extension_id())
68 return a.extension_id() < b.extension_id(); 203 return a.extension_id() < b.extension_id();
69 return a.warning_type() < b.warning_type(); 204 return a.warning_type() < b.warning_type();
70 } 205 }
71 206
72 // Static 207 } // namespace extensions
73 string16 ExtensionWarningSet::GetLocalizedWarning(
74 ExtensionWarningSet::WarningType warning_type) {
75 switch (warning_type) {
76 case kInvalid:
77 case kMaxWarningType:
78 NOTREACHED();
79 return string16();
80 case kNetworkDelay:
81 return l10n_util::GetStringFUTF16(
82 IDS_EXTENSION_WARNINGS_NETWORK_DELAY,
83 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
84 case kNetworkConflict:
85 return l10n_util::GetStringUTF16(IDS_EXTENSION_WARNINGS_NETWORK_CONFLICT);
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;
114 for (iterator i = warnings_.begin(); i != warnings_.end();) {
115 if (types.find(i->warning_type()) != types.end()) {
116 deleted_anything = true;
117 warnings_.erase(i++);
118 } else {
119 ++i;
120 }
121 }
122
123 if (deleted_anything) {
124 NotifyWarningsChanged();
125 UpdateWarningBadge();
126 }
127 }
128
129 void ExtensionWarningSet::GetWarningsAffectingExtension(
130 const std::string& extension_id,
131 std::set<ExtensionWarningSet::WarningType>* result) const {
132 result->clear();
133 for (const_iterator i = warnings_.begin(); i != warnings_.end(); ++i) {
134 if (i->extension_id() == extension_id)
135 result->insert(i->warning_type());
136 }
137 }
138
139 // static
140 void ExtensionWarningSet::NotifyWarningsOnUI(
141 void* profile_id,
142 std::set<std::string> extension_ids,
143 WarningType warning_type) {
144 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
145 Profile* profile = reinterpret_cast<Profile*>(profile_id);
146 if (!profile ||
147 !g_browser_process->profile_manager() ||
148 !g_browser_process->profile_manager()->IsValidProfile(profile)) {
149 return;
150 }
151
152 ExtensionWarningSet* warnings =
153 profile->GetExtensionService()->extension_warnings();
154
155 for (std::set<std::string>::const_iterator i = extension_ids.begin();
156 i != extension_ids.end(); ++i) {
157 warnings->SetWarning(warning_type, *i);
158 }
159 }
160
161 void ExtensionWarningSet::SuppressBadgeForCurrentWarnings() {
162 badge_suppressions_.insert(warnings_.begin(), warnings_.end());
163 UpdateWarningBadge();
164 }
165
166 void ExtensionWarningSet::NotifyWarningsChanged() {
167 content::NotificationService::current()->Notify(
168 chrome::NOTIFICATION_EXTENSION_WARNING_CHANGED,
169 content::Source<Profile>(profile_),
170 content::NotificationService::NoDetails());
171 }
172
173 void ExtensionWarningSet::UpdateWarningBadge() {
174 // We need a badge if a warning exists that has not been suppressed.
175 bool need_warning_badge = false;
176 for (const_iterator i = warnings_.begin(); i != warnings_.end(); ++i) {
177 if (badge_suppressions_.find(*i) == badge_suppressions_.end()) {
178 need_warning_badge = true;
179 break;
180 }
181 }
182
183 GlobalErrorService* service =
184 GlobalErrorServiceFactory::GetForProfile(profile_);
185 GlobalError* error = service->GetGlobalErrorByMenuItemCommandID(
186 ExtensionGlobalErrorBadge::GetMenuItemCommandID());
187
188 // Activate or hide the warning badge in case the current state is incorrect.
189 if (error && !need_warning_badge) {
190 service->RemoveGlobalError(error);
191 delete error;
192 } else if (!error && need_warning_badge) {
193 service->AddGlobalError(new ExtensionGlobalErrorBadge);
194 }
195 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698