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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h"
6
7 #include <limits>
8
9 #include "base/lazy_instance.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/values.h"
14 #include "chrome/browser/extensions/api/declarative/deduping_factory.h"
15 #include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h"
16 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h"
17 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h"
18 #include "chrome/browser/extensions/api/web_request/web_request_api_constants.h"
19 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h"
20 #include "chrome/browser/extensions/api/web_request/web_request_permissions.h"
21 #include "chrome/browser/extensions/extension_renderer_state.h"
22 #include "content/public/browser/resource_request_info.h"
23 #include "content/public/common/url_constants.h"
24 #include "extensions/browser/info_map.h"
25 #include "extensions/common/error_utils.h"
26 #include "extensions/common/extension.h"
27 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
28 #include "net/url_request/url_request.h"
29 #include "third_party/re2/re2/re2.h"
30
31 using content::ResourceRequestInfo;
32
33 namespace extensions {
34
35 namespace helpers = extension_web_request_api_helpers;
36 namespace keys = declarative_webrequest_constants;
37
38 namespace {
39 // Error messages.
40 const char kIgnoreRulesRequiresParameterError[] =
41 "IgnoreRules requires at least one parameter.";
42
43 const char kTransparentImageUrl[] = "data:image/png;base64,iVBORw0KGgoAAAANSUh"
44 "EUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==";
45 const char kEmptyDocumentUrl[] = "data:text/html,";
46
47 #define INPUT_FORMAT_VALIDATE(test) do { \
48 if (!(test)) { \
49 *bad_message = true; \
50 return scoped_refptr<const WebRequestAction>(NULL); \
51 } \
52 } while (0)
53
ParseRequestCookie(const base::DictionaryValue * dict)54 scoped_ptr<helpers::RequestCookie> ParseRequestCookie(
55 const base::DictionaryValue* dict) {
56 scoped_ptr<helpers::RequestCookie> result(new helpers::RequestCookie);
57 std::string tmp;
58 if (dict->GetString(keys::kNameKey, &tmp))
59 result->name.reset(new std::string(tmp));
60 if (dict->GetString(keys::kValueKey, &tmp))
61 result->value.reset(new std::string(tmp));
62 return result.Pass();
63 }
64
ParseResponseCookieImpl(const base::DictionaryValue * dict,helpers::ResponseCookie * cookie)65 void ParseResponseCookieImpl(const base::DictionaryValue* dict,
66 helpers::ResponseCookie* cookie) {
67 std::string string_tmp;
68 int int_tmp = 0;
69 bool bool_tmp = false;
70 if (dict->GetString(keys::kNameKey, &string_tmp))
71 cookie->name.reset(new std::string(string_tmp));
72 if (dict->GetString(keys::kValueKey, &string_tmp))
73 cookie->value.reset(new std::string(string_tmp));
74 if (dict->GetString(keys::kExpiresKey, &string_tmp))
75 cookie->expires.reset(new std::string(string_tmp));
76 if (dict->GetInteger(keys::kMaxAgeKey, &int_tmp))
77 cookie->max_age.reset(new int(int_tmp));
78 if (dict->GetString(keys::kDomainKey, &string_tmp))
79 cookie->domain.reset(new std::string(string_tmp));
80 if (dict->GetString(keys::kPathKey, &string_tmp))
81 cookie->path.reset(new std::string(string_tmp));
82 if (dict->GetBoolean(keys::kSecureKey, &bool_tmp))
83 cookie->secure.reset(new bool(bool_tmp));
84 if (dict->GetBoolean(keys::kHttpOnlyKey, &bool_tmp))
85 cookie->http_only.reset(new bool(bool_tmp));
86 }
87
ParseResponseCookie(const base::DictionaryValue * dict)88 scoped_ptr<helpers::ResponseCookie> ParseResponseCookie(
89 const base::DictionaryValue* dict) {
90 scoped_ptr<helpers::ResponseCookie> result(new helpers::ResponseCookie);
91 ParseResponseCookieImpl(dict, result.get());
92 return result.Pass();
93 }
94
ParseFilterResponseCookie(const base::DictionaryValue * dict)95 scoped_ptr<helpers::FilterResponseCookie> ParseFilterResponseCookie(
96 const base::DictionaryValue* dict) {
97 scoped_ptr<helpers::FilterResponseCookie> result(
98 new helpers::FilterResponseCookie);
99 ParseResponseCookieImpl(dict, result.get());
100
101 int int_tmp = 0;
102 bool bool_tmp = false;
103 if (dict->GetInteger(keys::kAgeUpperBoundKey, &int_tmp))
104 result->age_upper_bound.reset(new int(int_tmp));
105 if (dict->GetInteger(keys::kAgeLowerBoundKey, &int_tmp))
106 result->age_lower_bound.reset(new int(int_tmp));
107 if (dict->GetBoolean(keys::kSessionCookieKey, &bool_tmp))
108 result->session_cookie.reset(new bool(bool_tmp));
109 return result.Pass();
110 }
111
112 // Helper function for WebRequestActions that can be instantiated by just
113 // calling the constructor.
114 template <class T>
CallConstructorFactoryMethod(const std::string & instance_type,const base::Value * value,std::string * error,bool * bad_message)115 scoped_refptr<const WebRequestAction> CallConstructorFactoryMethod(
116 const std::string& instance_type,
117 const base::Value* value,
118 std::string* error,
119 bool* bad_message) {
120 return scoped_refptr<const WebRequestAction>(new T);
121 }
122
CreateRedirectRequestAction(const std::string & instance_type,const base::Value * value,std::string * error,bool * bad_message)123 scoped_refptr<const WebRequestAction> CreateRedirectRequestAction(
124 const std::string& instance_type,
125 const base::Value* value,
126 std::string* error,
127 bool* bad_message) {
128 const base::DictionaryValue* dict = NULL;
129 CHECK(value->GetAsDictionary(&dict));
130 std::string redirect_url_string;
131 INPUT_FORMAT_VALIDATE(
132 dict->GetString(keys::kRedirectUrlKey, &redirect_url_string));
133 GURL redirect_url(redirect_url_string);
134 return scoped_refptr<const WebRequestAction>(
135 new WebRequestRedirectAction(redirect_url));
136 }
137
CreateRedirectRequestByRegExAction(const std::string & instance_type,const base::Value * value,std::string * error,bool * bad_message)138 scoped_refptr<const WebRequestAction> CreateRedirectRequestByRegExAction(
139 const std::string& instance_type,
140 const base::Value* value,
141 std::string* error,
142 bool* bad_message) {
143 const base::DictionaryValue* dict = NULL;
144 CHECK(value->GetAsDictionary(&dict));
145 std::string from;
146 std::string to;
147 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kFromKey, &from));
148 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kToKey, &to));
149
150 to = WebRequestRedirectByRegExAction::PerlToRe2Style(to);
151
152 RE2::Options options;
153 options.set_case_sensitive(false);
154 scoped_ptr<RE2> from_pattern(new RE2(from, options));
155
156 if (!from_pattern->ok()) {
157 *error = "Invalid pattern '" + from + "' -> '" + to + "'";
158 return scoped_refptr<const WebRequestAction>(NULL);
159 }
160 return scoped_refptr<const WebRequestAction>(
161 new WebRequestRedirectByRegExAction(from_pattern.Pass(), to));
162 }
163
CreateSetRequestHeaderAction(const std::string & instance_type,const base::Value * json_value,std::string * error,bool * bad_message)164 scoped_refptr<const WebRequestAction> CreateSetRequestHeaderAction(
165 const std::string& instance_type,
166 const base::Value* json_value,
167 std::string* error,
168 bool* bad_message) {
169 const base::DictionaryValue* dict = NULL;
170 CHECK(json_value->GetAsDictionary(&dict));
171 std::string name;
172 std::string value;
173 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kNameKey, &name));
174 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kValueKey, &value));
175 if (!helpers::IsValidHeaderName(name)) {
176 *error = extension_web_request_api_constants::kInvalidHeaderName;
177 return scoped_refptr<const WebRequestAction>(NULL);
178 }
179 if (!helpers::IsValidHeaderValue(value)) {
180 *error = ErrorUtils::FormatErrorMessage(
181 extension_web_request_api_constants::kInvalidHeaderValue, name);
182 return scoped_refptr<const WebRequestAction>(NULL);
183 }
184 return scoped_refptr<const WebRequestAction>(
185 new WebRequestSetRequestHeaderAction(name, value));
186 }
187
CreateRemoveRequestHeaderAction(const std::string & instance_type,const base::Value * value,std::string * error,bool * bad_message)188 scoped_refptr<const WebRequestAction> CreateRemoveRequestHeaderAction(
189 const std::string& instance_type,
190 const base::Value* value,
191 std::string* error,
192 bool* bad_message) {
193 const base::DictionaryValue* dict = NULL;
194 CHECK(value->GetAsDictionary(&dict));
195 std::string name;
196 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kNameKey, &name));
197 if (!helpers::IsValidHeaderName(name)) {
198 *error = extension_web_request_api_constants::kInvalidHeaderName;
199 return scoped_refptr<const WebRequestAction>(NULL);
200 }
201 return scoped_refptr<const WebRequestAction>(
202 new WebRequestRemoveRequestHeaderAction(name));
203 }
204
CreateAddResponseHeaderAction(const std::string & instance_type,const base::Value * json_value,std::string * error,bool * bad_message)205 scoped_refptr<const WebRequestAction> CreateAddResponseHeaderAction(
206 const std::string& instance_type,
207 const base::Value* json_value,
208 std::string* error,
209 bool* bad_message) {
210 const base::DictionaryValue* dict = NULL;
211 CHECK(json_value->GetAsDictionary(&dict));
212 std::string name;
213 std::string value;
214 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kNameKey, &name));
215 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kValueKey, &value));
216 if (!helpers::IsValidHeaderName(name)) {
217 *error = extension_web_request_api_constants::kInvalidHeaderName;
218 return scoped_refptr<const WebRequestAction>(NULL);
219 }
220 if (!helpers::IsValidHeaderValue(value)) {
221 *error = ErrorUtils::FormatErrorMessage(
222 extension_web_request_api_constants::kInvalidHeaderValue, name);
223 return scoped_refptr<const WebRequestAction>(NULL);
224 }
225 return scoped_refptr<const WebRequestAction>(
226 new WebRequestAddResponseHeaderAction(name, value));
227 }
228
CreateRemoveResponseHeaderAction(const std::string & instance_type,const base::Value * json_value,std::string * error,bool * bad_message)229 scoped_refptr<const WebRequestAction> CreateRemoveResponseHeaderAction(
230 const std::string& instance_type,
231 const base::Value* json_value,
232 std::string* error,
233 bool* bad_message) {
234 const base::DictionaryValue* dict = NULL;
235 CHECK(json_value->GetAsDictionary(&dict));
236 std::string name;
237 std::string value;
238 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kNameKey, &name));
239 bool has_value = dict->GetString(keys::kValueKey, &value);
240 if (!helpers::IsValidHeaderName(name)) {
241 *error = extension_web_request_api_constants::kInvalidHeaderName;
242 return scoped_refptr<const WebRequestAction>(NULL);
243 }
244 if (has_value && !helpers::IsValidHeaderValue(value)) {
245 *error = ErrorUtils::FormatErrorMessage(
246 extension_web_request_api_constants::kInvalidHeaderValue, name);
247 return scoped_refptr<const WebRequestAction>(NULL);
248 }
249 return scoped_refptr<const WebRequestAction>(
250 new WebRequestRemoveResponseHeaderAction(name, value, has_value));
251 }
252
CreateIgnoreRulesAction(const std::string & instance_type,const base::Value * value,std::string * error,bool * bad_message)253 scoped_refptr<const WebRequestAction> CreateIgnoreRulesAction(
254 const std::string& instance_type,
255 const base::Value* value,
256 std::string* error,
257 bool* bad_message) {
258 const base::DictionaryValue* dict = NULL;
259 CHECK(value->GetAsDictionary(&dict));
260 bool has_parameter = false;
261 int minimum_priority = std::numeric_limits<int>::min();
262 std::string ignore_tag;
263 if (dict->HasKey(keys::kLowerPriorityThanKey)) {
264 INPUT_FORMAT_VALIDATE(
265 dict->GetInteger(keys::kLowerPriorityThanKey, &minimum_priority));
266 has_parameter = true;
267 }
268 if (dict->HasKey(keys::kHasTagKey)) {
269 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kHasTagKey, &ignore_tag));
270 has_parameter = true;
271 }
272 if (!has_parameter) {
273 *error = kIgnoreRulesRequiresParameterError;
274 return scoped_refptr<const WebRequestAction>(NULL);
275 }
276 return scoped_refptr<const WebRequestAction>(
277 new WebRequestIgnoreRulesAction(minimum_priority, ignore_tag));
278 }
279
CreateRequestCookieAction(const std::string & instance_type,const base::Value * value,std::string * error,bool * bad_message)280 scoped_refptr<const WebRequestAction> CreateRequestCookieAction(
281 const std::string& instance_type,
282 const base::Value* value,
283 std::string* error,
284 bool* bad_message) {
285 using extension_web_request_api_helpers::RequestCookieModification;
286
287 const base::DictionaryValue* dict = NULL;
288 CHECK(value->GetAsDictionary(&dict));
289
290 linked_ptr<RequestCookieModification> modification(
291 new RequestCookieModification);
292
293 // Get modification type.
294 if (instance_type == keys::kAddRequestCookieType)
295 modification->type = helpers::ADD;
296 else if (instance_type == keys::kEditRequestCookieType)
297 modification->type = helpers::EDIT;
298 else if (instance_type == keys::kRemoveRequestCookieType)
299 modification->type = helpers::REMOVE;
300 else
301 INPUT_FORMAT_VALIDATE(false);
302
303 // Get filter.
304 if (modification->type == helpers::EDIT ||
305 modification->type == helpers::REMOVE) {
306 const base::DictionaryValue* filter = NULL;
307 INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kFilterKey, &filter));
308 modification->filter = ParseRequestCookie(filter);
309 }
310
311 // Get new value.
312 if (modification->type == helpers::ADD) {
313 const base::DictionaryValue* value = NULL;
314 INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kCookieKey, &value));
315 modification->modification = ParseRequestCookie(value);
316 } else if (modification->type == helpers::EDIT) {
317 const base::DictionaryValue* value = NULL;
318 INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kModificationKey, &value));
319 modification->modification = ParseRequestCookie(value);
320 }
321
322 return scoped_refptr<const WebRequestAction>(
323 new WebRequestRequestCookieAction(modification));
324 }
325
CreateResponseCookieAction(const std::string & instance_type,const base::Value * value,std::string * error,bool * bad_message)326 scoped_refptr<const WebRequestAction> CreateResponseCookieAction(
327 const std::string& instance_type,
328 const base::Value* value,
329 std::string* error,
330 bool* bad_message) {
331 using extension_web_request_api_helpers::ResponseCookieModification;
332
333 const base::DictionaryValue* dict = NULL;
334 CHECK(value->GetAsDictionary(&dict));
335
336 linked_ptr<ResponseCookieModification> modification(
337 new ResponseCookieModification);
338
339 // Get modification type.
340 if (instance_type == keys::kAddResponseCookieType)
341 modification->type = helpers::ADD;
342 else if (instance_type == keys::kEditResponseCookieType)
343 modification->type = helpers::EDIT;
344 else if (instance_type == keys::kRemoveResponseCookieType)
345 modification->type = helpers::REMOVE;
346 else
347 INPUT_FORMAT_VALIDATE(false);
348
349 // Get filter.
350 if (modification->type == helpers::EDIT ||
351 modification->type == helpers::REMOVE) {
352 const base::DictionaryValue* filter = NULL;
353 INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kFilterKey, &filter));
354 modification->filter = ParseFilterResponseCookie(filter);
355 }
356
357 // Get new value.
358 if (modification->type == helpers::ADD) {
359 const base::DictionaryValue* value = NULL;
360 INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kCookieKey, &value));
361 modification->modification = ParseResponseCookie(value);
362 } else if (modification->type == helpers::EDIT) {
363 const base::DictionaryValue* value = NULL;
364 INPUT_FORMAT_VALIDATE(dict->GetDictionary(keys::kModificationKey, &value));
365 modification->modification = ParseResponseCookie(value);
366 }
367
368 return scoped_refptr<const WebRequestAction>(
369 new WebRequestResponseCookieAction(modification));
370 }
371
CreateSendMessageToExtensionAction(const std::string & name,const base::Value * value,std::string * error,bool * bad_message)372 scoped_refptr<const WebRequestAction> CreateSendMessageToExtensionAction(
373 const std::string& name,
374 const base::Value* value,
375 std::string* error,
376 bool* bad_message) {
377 const base::DictionaryValue* dict = NULL;
378 CHECK(value->GetAsDictionary(&dict));
379 std::string message;
380 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kMessageKey, &message));
381 return scoped_refptr<const WebRequestAction>(
382 new WebRequestSendMessageToExtensionAction(message));
383 }
384
385 struct WebRequestActionFactory {
386 DedupingFactory<WebRequestAction> factory;
387
WebRequestActionFactoryextensions::__anon840fc4480111::WebRequestActionFactory388 WebRequestActionFactory() : factory(5) {
389 factory.RegisterFactoryMethod(
390 keys::kAddRequestCookieType,
391 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
392 &CreateRequestCookieAction);
393 factory.RegisterFactoryMethod(
394 keys::kAddResponseCookieType,
395 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
396 &CreateResponseCookieAction);
397 factory.RegisterFactoryMethod(
398 keys::kAddResponseHeaderType,
399 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
400 &CreateAddResponseHeaderAction);
401 factory.RegisterFactoryMethod(
402 keys::kCancelRequestType,
403 DedupingFactory<WebRequestAction>::IS_NOT_PARAMETERIZED,
404 &CallConstructorFactoryMethod<WebRequestCancelAction>);
405 factory.RegisterFactoryMethod(
406 keys::kEditRequestCookieType,
407 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
408 &CreateRequestCookieAction);
409 factory.RegisterFactoryMethod(
410 keys::kEditResponseCookieType,
411 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
412 &CreateResponseCookieAction);
413 factory.RegisterFactoryMethod(
414 keys::kRedirectByRegExType,
415 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
416 &CreateRedirectRequestByRegExAction);
417 factory.RegisterFactoryMethod(
418 keys::kRedirectRequestType,
419 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
420 &CreateRedirectRequestAction);
421 factory.RegisterFactoryMethod(
422 keys::kRedirectToTransparentImageType,
423 DedupingFactory<WebRequestAction>::IS_NOT_PARAMETERIZED,
424 &CallConstructorFactoryMethod<
425 WebRequestRedirectToTransparentImageAction>);
426 factory.RegisterFactoryMethod(
427 keys::kRedirectToEmptyDocumentType,
428 DedupingFactory<WebRequestAction>::IS_NOT_PARAMETERIZED,
429 &CallConstructorFactoryMethod<WebRequestRedirectToEmptyDocumentAction>);
430 factory.RegisterFactoryMethod(
431 keys::kRemoveRequestCookieType,
432 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
433 &CreateRequestCookieAction);
434 factory.RegisterFactoryMethod(
435 keys::kRemoveResponseCookieType,
436 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
437 &CreateResponseCookieAction);
438 factory.RegisterFactoryMethod(
439 keys::kSetRequestHeaderType,
440 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
441 &CreateSetRequestHeaderAction);
442 factory.RegisterFactoryMethod(
443 keys::kRemoveRequestHeaderType,
444 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
445 &CreateRemoveRequestHeaderAction);
446 factory.RegisterFactoryMethod(
447 keys::kRemoveResponseHeaderType,
448 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
449 &CreateRemoveResponseHeaderAction);
450 factory.RegisterFactoryMethod(
451 keys::kIgnoreRulesType,
452 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
453 &CreateIgnoreRulesAction);
454 factory.RegisterFactoryMethod(
455 keys::kSendMessageToExtensionType,
456 DedupingFactory<WebRequestAction>::IS_PARAMETERIZED,
457 &CreateSendMessageToExtensionAction);
458 }
459 };
460
461 base::LazyInstance<WebRequestActionFactory>::Leaky
462 g_web_request_action_factory = LAZY_INSTANCE_INITIALIZER;
463
464 } // namespace
465
466 //
467 // WebRequestAction
468 //
469
~WebRequestAction()470 WebRequestAction::~WebRequestAction() {}
471
Equals(const WebRequestAction * other) const472 bool WebRequestAction::Equals(const WebRequestAction* other) const {
473 return type() == other->type();
474 }
475
HasPermission(const InfoMap * extension_info_map,const std::string & extension_id,const net::URLRequest * request,bool crosses_incognito) const476 bool WebRequestAction::HasPermission(const InfoMap* extension_info_map,
477 const std::string& extension_id,
478 const net::URLRequest* request,
479 bool crosses_incognito) const {
480 if (WebRequestPermissions::HideRequest(extension_info_map, request))
481 return false;
482
483 // In unit tests we don't have an extension_info_map object here and skip host
484 // permission checks.
485 if (!extension_info_map)
486 return true;
487
488 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
489 int process_id = info ? info->GetChildID() : 0;
490 int route_id = info ? info->GetRouteID() : 0;
491 ExtensionRendererState::WebViewInfo webview_info;
492 // The embedder can always access all hosts from within a <webview>.
493 // The same is not true of extensions.
494 if (ExtensionRendererState::GetInstance()->GetWebViewInfo(
495 process_id, route_id, &webview_info)) {
496 return true;
497 }
498 WebRequestPermissions::HostPermissionsCheck permission_check =
499 WebRequestPermissions::REQUIRE_ALL_URLS;
500 switch (host_permissions_strategy()) {
501 case STRATEGY_DEFAULT: // Default value is already set.
502 break;
503 case STRATEGY_NONE:
504 permission_check = WebRequestPermissions::DO_NOT_CHECK_HOST;
505 break;
506 case STRATEGY_HOST:
507 permission_check = WebRequestPermissions::REQUIRE_HOST_PERMISSION;
508 break;
509 }
510 return WebRequestPermissions::CanExtensionAccessURL(
511 extension_info_map, extension_id, request->url(), crosses_incognito,
512 permission_check);
513 }
514
515 // static
Create(const Extension * extension,const base::Value & json_action,std::string * error,bool * bad_message)516 scoped_refptr<const WebRequestAction> WebRequestAction::Create(
517 const Extension* extension,
518 const base::Value& json_action,
519 std::string* error,
520 bool* bad_message) {
521 *error = "";
522 *bad_message = false;
523
524 const base::DictionaryValue* action_dict = NULL;
525 INPUT_FORMAT_VALIDATE(json_action.GetAsDictionary(&action_dict));
526
527 std::string instance_type;
528 INPUT_FORMAT_VALIDATE(
529 action_dict->GetString(keys::kInstanceTypeKey, &instance_type));
530
531 WebRequestActionFactory& factory = g_web_request_action_factory.Get();
532 return factory.factory.Instantiate(
533 instance_type, action_dict, error, bad_message);
534 }
535
Apply(const std::string & extension_id,base::Time extension_install_time,ApplyInfo * apply_info) const536 void WebRequestAction::Apply(const std::string& extension_id,
537 base::Time extension_install_time,
538 ApplyInfo* apply_info) const {
539 if (!HasPermission(apply_info->extension_info_map, extension_id,
540 apply_info->request_data.request,
541 apply_info->crosses_incognito))
542 return;
543 if (stages() & apply_info->request_data.stage) {
544 LinkedPtrEventResponseDelta delta = CreateDelta(
545 apply_info->request_data, extension_id, extension_install_time);
546 if (delta.get())
547 apply_info->deltas->push_back(delta);
548 if (type() == WebRequestAction::ACTION_IGNORE_RULES) {
549 const WebRequestIgnoreRulesAction* ignore_action =
550 static_cast<const WebRequestIgnoreRulesAction*>(this);
551 if (!ignore_action->ignore_tag().empty())
552 apply_info->ignored_tags->insert(ignore_action->ignore_tag());
553 }
554 }
555 }
556
WebRequestAction(int stages,Type type,int minimum_priority,HostPermissionsStrategy strategy)557 WebRequestAction::WebRequestAction(int stages,
558 Type type,
559 int minimum_priority,
560 HostPermissionsStrategy strategy)
561 : stages_(stages),
562 type_(type),
563 minimum_priority_(minimum_priority),
564 host_permissions_strategy_(strategy) {}
565
566 //
567 // WebRequestCancelAction
568 //
569
WebRequestCancelAction()570 WebRequestCancelAction::WebRequestCancelAction()
571 : WebRequestAction(ON_BEFORE_REQUEST | ON_BEFORE_SEND_HEADERS |
572 ON_HEADERS_RECEIVED | ON_AUTH_REQUIRED,
573 ACTION_CANCEL_REQUEST,
574 std::numeric_limits<int>::min(),
575 STRATEGY_NONE) {}
576
~WebRequestCancelAction()577 WebRequestCancelAction::~WebRequestCancelAction() {}
578
GetName() const579 std::string WebRequestCancelAction::GetName() const {
580 return keys::kCancelRequestType;
581 }
582
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const583 LinkedPtrEventResponseDelta WebRequestCancelAction::CreateDelta(
584 const WebRequestData& request_data,
585 const std::string& extension_id,
586 const base::Time& extension_install_time) const {
587 CHECK(request_data.stage & stages());
588 LinkedPtrEventResponseDelta result(
589 new helpers::EventResponseDelta(extension_id, extension_install_time));
590 result->cancel = true;
591 return result;
592 }
593
594 //
595 // WebRequestRedirectAction
596 //
597
WebRequestRedirectAction(const GURL & redirect_url)598 WebRequestRedirectAction::WebRequestRedirectAction(const GURL& redirect_url)
599 : WebRequestAction(ON_BEFORE_REQUEST | ON_HEADERS_RECEIVED,
600 ACTION_REDIRECT_REQUEST,
601 std::numeric_limits<int>::min(),
602 STRATEGY_DEFAULT),
603 redirect_url_(redirect_url) {}
604
~WebRequestRedirectAction()605 WebRequestRedirectAction::~WebRequestRedirectAction() {}
606
Equals(const WebRequestAction * other) const607 bool WebRequestRedirectAction::Equals(const WebRequestAction* other) const {
608 return WebRequestAction::Equals(other) &&
609 redirect_url_ ==
610 static_cast<const WebRequestRedirectAction*>(other)->redirect_url_;
611 }
612
GetName() const613 std::string WebRequestRedirectAction::GetName() const {
614 return keys::kRedirectRequestType;
615 }
616
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const617 LinkedPtrEventResponseDelta WebRequestRedirectAction::CreateDelta(
618 const WebRequestData& request_data,
619 const std::string& extension_id,
620 const base::Time& extension_install_time) const {
621 CHECK(request_data.stage & stages());
622 if (request_data.request->url() == redirect_url_)
623 return LinkedPtrEventResponseDelta(NULL);
624 LinkedPtrEventResponseDelta result(
625 new helpers::EventResponseDelta(extension_id, extension_install_time));
626 result->new_url = redirect_url_;
627 return result;
628 }
629
630 //
631 // WebRequestRedirectToTransparentImageAction
632 //
633
634 WebRequestRedirectToTransparentImageAction::
WebRequestRedirectToTransparentImageAction()635 WebRequestRedirectToTransparentImageAction()
636 : WebRequestAction(ON_BEFORE_REQUEST | ON_HEADERS_RECEIVED,
637 ACTION_REDIRECT_TO_TRANSPARENT_IMAGE,
638 std::numeric_limits<int>::min(),
639 STRATEGY_NONE) {}
640
641 WebRequestRedirectToTransparentImageAction::
~WebRequestRedirectToTransparentImageAction()642 ~WebRequestRedirectToTransparentImageAction() {}
643
GetName() const644 std::string WebRequestRedirectToTransparentImageAction::GetName() const {
645 return keys::kRedirectToTransparentImageType;
646 }
647
648 LinkedPtrEventResponseDelta
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const649 WebRequestRedirectToTransparentImageAction::CreateDelta(
650 const WebRequestData& request_data,
651 const std::string& extension_id,
652 const base::Time& extension_install_time) const {
653 CHECK(request_data.stage & stages());
654 LinkedPtrEventResponseDelta result(
655 new helpers::EventResponseDelta(extension_id, extension_install_time));
656 result->new_url = GURL(kTransparentImageUrl);
657 return result;
658 }
659
660 //
661 // WebRequestRedirectToEmptyDocumentAction
662 //
663
664 WebRequestRedirectToEmptyDocumentAction::
WebRequestRedirectToEmptyDocumentAction()665 WebRequestRedirectToEmptyDocumentAction()
666 : WebRequestAction(ON_BEFORE_REQUEST | ON_HEADERS_RECEIVED,
667 ACTION_REDIRECT_TO_EMPTY_DOCUMENT,
668 std::numeric_limits<int>::min(),
669 STRATEGY_NONE) {}
670
671 WebRequestRedirectToEmptyDocumentAction::
~WebRequestRedirectToEmptyDocumentAction()672 ~WebRequestRedirectToEmptyDocumentAction() {}
673
GetName() const674 std::string WebRequestRedirectToEmptyDocumentAction::GetName() const {
675 return keys::kRedirectToEmptyDocumentType;
676 }
677
678 LinkedPtrEventResponseDelta
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const679 WebRequestRedirectToEmptyDocumentAction::CreateDelta(
680 const WebRequestData& request_data,
681 const std::string& extension_id,
682 const base::Time& extension_install_time) const {
683 CHECK(request_data.stage & stages());
684 LinkedPtrEventResponseDelta result(
685 new helpers::EventResponseDelta(extension_id, extension_install_time));
686 result->new_url = GURL(kEmptyDocumentUrl);
687 return result;
688 }
689
690 //
691 // WebRequestRedirectByRegExAction
692 //
693
WebRequestRedirectByRegExAction(scoped_ptr<RE2> from_pattern,const std::string & to_pattern)694 WebRequestRedirectByRegExAction::WebRequestRedirectByRegExAction(
695 scoped_ptr<RE2> from_pattern,
696 const std::string& to_pattern)
697 : WebRequestAction(ON_BEFORE_REQUEST | ON_HEADERS_RECEIVED,
698 ACTION_REDIRECT_BY_REGEX_DOCUMENT,
699 std::numeric_limits<int>::min(),
700 STRATEGY_DEFAULT),
701 from_pattern_(from_pattern.Pass()),
702 to_pattern_(to_pattern.data(), to_pattern.size()) {}
703
~WebRequestRedirectByRegExAction()704 WebRequestRedirectByRegExAction::~WebRequestRedirectByRegExAction() {}
705
706 // About the syntax of the two languages:
707 //
708 // ICU (Perl) states:
709 // $n The text of capture group n will be substituted for $n. n must be >= 0
710 // and not greater than the number of capture groups. A $ not followed by a
711 // digit has no special meaning, and will appear in the substitution text
712 // as itself, a $.
713 // \ Treat the following character as a literal, suppressing any special
714 // meaning. Backslash escaping in substitution text is only required for
715 // '$' and '\', but may be used on any other character without bad effects.
716 //
717 // RE2, derived from RE2::Rewrite()
718 // \ May only be followed by a digit or another \. If followed by a single
719 // digit, both characters represent the respective capture group. If followed
720 // by another \, it is used as an escape sequence.
721
722 // static
PerlToRe2Style(const std::string & perl)723 std::string WebRequestRedirectByRegExAction::PerlToRe2Style(
724 const std::string& perl) {
725 std::string::const_iterator i = perl.begin();
726 std::string result;
727 while (i != perl.end()) {
728 if (*i == '$') {
729 ++i;
730 if (i == perl.end()) {
731 result += '$';
732 return result;
733 } else if (isdigit(*i)) {
734 result += '\\';
735 result += *i;
736 } else {
737 result += '$';
738 result += *i;
739 }
740 } else if (*i == '\\') {
741 ++i;
742 if (i == perl.end()) {
743 result += '\\';
744 } else if (*i == '$') {
745 result += '$';
746 } else if (*i == '\\') {
747 result += "\\\\";
748 } else {
749 result += *i;
750 }
751 } else {
752 result += *i;
753 }
754 ++i;
755 }
756 return result;
757 }
758
Equals(const WebRequestAction * other) const759 bool WebRequestRedirectByRegExAction::Equals(
760 const WebRequestAction* other) const {
761 if (!WebRequestAction::Equals(other))
762 return false;
763 const WebRequestRedirectByRegExAction* casted_other =
764 static_cast<const WebRequestRedirectByRegExAction*>(other);
765 return from_pattern_->pattern() == casted_other->from_pattern_->pattern() &&
766 to_pattern_ == casted_other->to_pattern_;
767 }
768
GetName() const769 std::string WebRequestRedirectByRegExAction::GetName() const {
770 return keys::kRedirectByRegExType;
771 }
772
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const773 LinkedPtrEventResponseDelta WebRequestRedirectByRegExAction::CreateDelta(
774 const WebRequestData& request_data,
775 const std::string& extension_id,
776 const base::Time& extension_install_time) const {
777 CHECK(request_data.stage & stages());
778 CHECK(from_pattern_.get());
779
780 const std::string& old_url = request_data.request->url().spec();
781 std::string new_url = old_url;
782 if (!RE2::Replace(&new_url, *from_pattern_, to_pattern_) ||
783 new_url == old_url) {
784 return LinkedPtrEventResponseDelta(NULL);
785 }
786
787 LinkedPtrEventResponseDelta result(
788 new extension_web_request_api_helpers::EventResponseDelta(
789 extension_id, extension_install_time));
790 result->new_url = GURL(new_url);
791 return result;
792 }
793
794 //
795 // WebRequestSetRequestHeaderAction
796 //
797
WebRequestSetRequestHeaderAction(const std::string & name,const std::string & value)798 WebRequestSetRequestHeaderAction::WebRequestSetRequestHeaderAction(
799 const std::string& name,
800 const std::string& value)
801 : WebRequestAction(ON_BEFORE_SEND_HEADERS,
802 ACTION_SET_REQUEST_HEADER,
803 std::numeric_limits<int>::min(),
804 STRATEGY_DEFAULT),
805 name_(name),
806 value_(value) {}
807
~WebRequestSetRequestHeaderAction()808 WebRequestSetRequestHeaderAction::~WebRequestSetRequestHeaderAction() {}
809
Equals(const WebRequestAction * other) const810 bool WebRequestSetRequestHeaderAction::Equals(
811 const WebRequestAction* other) const {
812 if (!WebRequestAction::Equals(other))
813 return false;
814 const WebRequestSetRequestHeaderAction* casted_other =
815 static_cast<const WebRequestSetRequestHeaderAction*>(other);
816 return name_ == casted_other->name_ && value_ == casted_other->value_;
817 }
818
GetName() const819 std::string WebRequestSetRequestHeaderAction::GetName() const {
820 return keys::kSetRequestHeaderType;
821 }
822
823
824 LinkedPtrEventResponseDelta
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const825 WebRequestSetRequestHeaderAction::CreateDelta(
826 const WebRequestData& request_data,
827 const std::string& extension_id,
828 const base::Time& extension_install_time) const {
829 CHECK(request_data.stage & stages());
830 LinkedPtrEventResponseDelta result(
831 new helpers::EventResponseDelta(extension_id, extension_install_time));
832 result->modified_request_headers.SetHeader(name_, value_);
833 return result;
834 }
835
836 //
837 // WebRequestRemoveRequestHeaderAction
838 //
839
WebRequestRemoveRequestHeaderAction(const std::string & name)840 WebRequestRemoveRequestHeaderAction::WebRequestRemoveRequestHeaderAction(
841 const std::string& name)
842 : WebRequestAction(ON_BEFORE_SEND_HEADERS,
843 ACTION_REMOVE_REQUEST_HEADER,
844 std::numeric_limits<int>::min(),
845 STRATEGY_DEFAULT),
846 name_(name) {}
847
~WebRequestRemoveRequestHeaderAction()848 WebRequestRemoveRequestHeaderAction::~WebRequestRemoveRequestHeaderAction() {}
849
Equals(const WebRequestAction * other) const850 bool WebRequestRemoveRequestHeaderAction::Equals(
851 const WebRequestAction* other) const {
852 if (!WebRequestAction::Equals(other))
853 return false;
854 const WebRequestRemoveRequestHeaderAction* casted_other =
855 static_cast<const WebRequestRemoveRequestHeaderAction*>(other);
856 return name_ == casted_other->name_;
857 }
858
GetName() const859 std::string WebRequestRemoveRequestHeaderAction::GetName() const {
860 return keys::kRemoveRequestHeaderType;
861 }
862
863 LinkedPtrEventResponseDelta
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const864 WebRequestRemoveRequestHeaderAction::CreateDelta(
865 const WebRequestData& request_data,
866 const std::string& extension_id,
867 const base::Time& extension_install_time) const {
868 CHECK(request_data.stage & stages());
869 LinkedPtrEventResponseDelta result(
870 new helpers::EventResponseDelta(extension_id, extension_install_time));
871 result->deleted_request_headers.push_back(name_);
872 return result;
873 }
874
875 //
876 // WebRequestAddResponseHeaderAction
877 //
878
WebRequestAddResponseHeaderAction(const std::string & name,const std::string & value)879 WebRequestAddResponseHeaderAction::WebRequestAddResponseHeaderAction(
880 const std::string& name,
881 const std::string& value)
882 : WebRequestAction(ON_HEADERS_RECEIVED,
883 ACTION_ADD_RESPONSE_HEADER,
884 std::numeric_limits<int>::min(),
885 STRATEGY_DEFAULT),
886 name_(name),
887 value_(value) {}
888
~WebRequestAddResponseHeaderAction()889 WebRequestAddResponseHeaderAction::~WebRequestAddResponseHeaderAction() {}
890
Equals(const WebRequestAction * other) const891 bool WebRequestAddResponseHeaderAction::Equals(
892 const WebRequestAction* other) const {
893 if (!WebRequestAction::Equals(other))
894 return false;
895 const WebRequestAddResponseHeaderAction* casted_other =
896 static_cast<const WebRequestAddResponseHeaderAction*>(other);
897 return name_ == casted_other->name_ && value_ == casted_other->value_;
898 }
899
GetName() const900 std::string WebRequestAddResponseHeaderAction::GetName() const {
901 return keys::kAddResponseHeaderType;
902 }
903
904 LinkedPtrEventResponseDelta
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const905 WebRequestAddResponseHeaderAction::CreateDelta(
906 const WebRequestData& request_data,
907 const std::string& extension_id,
908 const base::Time& extension_install_time) const {
909 CHECK(request_data.stage & stages());
910 const net::HttpResponseHeaders* headers =
911 request_data.original_response_headers;
912 if (!headers)
913 return LinkedPtrEventResponseDelta(NULL);
914
915 // Don't generate the header if it exists already.
916 if (headers->HasHeaderValue(name_, value_))
917 return LinkedPtrEventResponseDelta(NULL);
918
919 LinkedPtrEventResponseDelta result(
920 new helpers::EventResponseDelta(extension_id, extension_install_time));
921 result->added_response_headers.push_back(make_pair(name_, value_));
922 return result;
923 }
924
925 //
926 // WebRequestRemoveResponseHeaderAction
927 //
928
WebRequestRemoveResponseHeaderAction(const std::string & name,const std::string & value,bool has_value)929 WebRequestRemoveResponseHeaderAction::WebRequestRemoveResponseHeaderAction(
930 const std::string& name,
931 const std::string& value,
932 bool has_value)
933 : WebRequestAction(ON_HEADERS_RECEIVED,
934 ACTION_REMOVE_RESPONSE_HEADER,
935 std::numeric_limits<int>::min(),
936 STRATEGY_DEFAULT),
937 name_(name),
938 value_(value),
939 has_value_(has_value) {}
940
~WebRequestRemoveResponseHeaderAction()941 WebRequestRemoveResponseHeaderAction::~WebRequestRemoveResponseHeaderAction() {}
942
Equals(const WebRequestAction * other) const943 bool WebRequestRemoveResponseHeaderAction::Equals(
944 const WebRequestAction* other) const {
945 if (!WebRequestAction::Equals(other))
946 return false;
947 const WebRequestRemoveResponseHeaderAction* casted_other =
948 static_cast<const WebRequestRemoveResponseHeaderAction*>(other);
949 return name_ == casted_other->name_ && value_ == casted_other->value_ &&
950 has_value_ == casted_other->has_value_;
951 }
952
GetName() const953 std::string WebRequestRemoveResponseHeaderAction::GetName() const {
954 return keys::kRemoveResponseHeaderType;
955 }
956
957 LinkedPtrEventResponseDelta
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const958 WebRequestRemoveResponseHeaderAction::CreateDelta(
959 const WebRequestData& request_data,
960 const std::string& extension_id,
961 const base::Time& extension_install_time) const {
962 CHECK(request_data.stage & stages());
963 const net::HttpResponseHeaders* headers =
964 request_data.original_response_headers;
965 if (!headers)
966 return LinkedPtrEventResponseDelta(NULL);
967
968 LinkedPtrEventResponseDelta result(
969 new helpers::EventResponseDelta(extension_id, extension_install_time));
970 void* iter = NULL;
971 std::string current_value;
972 while (headers->EnumerateHeader(&iter, name_, ¤t_value)) {
973 if (has_value_ &&
974 (current_value.size() != value_.size() ||
975 !std::equal(current_value.begin(), current_value.end(),
976 value_.begin(),
977 base::CaseInsensitiveCompare<char>()))) {
978 continue;
979 }
980 result->deleted_response_headers.push_back(make_pair(name_, current_value));
981 }
982 return result;
983 }
984
985 //
986 // WebRequestIgnoreRulesAction
987 //
988
WebRequestIgnoreRulesAction(int minimum_priority,const std::string & ignore_tag)989 WebRequestIgnoreRulesAction::WebRequestIgnoreRulesAction(
990 int minimum_priority,
991 const std::string& ignore_tag)
992 : WebRequestAction(ON_BEFORE_REQUEST | ON_BEFORE_SEND_HEADERS |
993 ON_HEADERS_RECEIVED | ON_AUTH_REQUIRED,
994 ACTION_IGNORE_RULES,
995 minimum_priority,
996 STRATEGY_NONE),
997 ignore_tag_(ignore_tag) {}
998
~WebRequestIgnoreRulesAction()999 WebRequestIgnoreRulesAction::~WebRequestIgnoreRulesAction() {}
1000
Equals(const WebRequestAction * other) const1001 bool WebRequestIgnoreRulesAction::Equals(const WebRequestAction* other) const {
1002 if (!WebRequestAction::Equals(other))
1003 return false;
1004 const WebRequestIgnoreRulesAction* casted_other =
1005 static_cast<const WebRequestIgnoreRulesAction*>(other);
1006 return minimum_priority() == casted_other->minimum_priority() &&
1007 ignore_tag_ == casted_other->ignore_tag_;
1008 }
1009
GetName() const1010 std::string WebRequestIgnoreRulesAction::GetName() const {
1011 return keys::kIgnoreRulesType;
1012 }
1013
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const1014 LinkedPtrEventResponseDelta WebRequestIgnoreRulesAction::CreateDelta(
1015 const WebRequestData& request_data,
1016 const std::string& extension_id,
1017 const base::Time& extension_install_time) const {
1018 CHECK(request_data.stage & stages());
1019 return LinkedPtrEventResponseDelta(NULL);
1020 }
1021
1022 //
1023 // WebRequestRequestCookieAction
1024 //
1025
WebRequestRequestCookieAction(linked_ptr<RequestCookieModification> request_cookie_modification)1026 WebRequestRequestCookieAction::WebRequestRequestCookieAction(
1027 linked_ptr<RequestCookieModification> request_cookie_modification)
1028 : WebRequestAction(ON_BEFORE_SEND_HEADERS,
1029 ACTION_MODIFY_REQUEST_COOKIE,
1030 std::numeric_limits<int>::min(),
1031 STRATEGY_DEFAULT),
1032 request_cookie_modification_(request_cookie_modification) {
1033 CHECK(request_cookie_modification_.get());
1034 }
1035
~WebRequestRequestCookieAction()1036 WebRequestRequestCookieAction::~WebRequestRequestCookieAction() {}
1037
Equals(const WebRequestAction * other) const1038 bool WebRequestRequestCookieAction::Equals(
1039 const WebRequestAction* other) const {
1040 if (!WebRequestAction::Equals(other))
1041 return false;
1042 const WebRequestRequestCookieAction* casted_other =
1043 static_cast<const WebRequestRequestCookieAction*>(other);
1044 return helpers::NullableEquals(
1045 request_cookie_modification_.get(),
1046 casted_other->request_cookie_modification_.get());
1047 }
1048
GetName() const1049 std::string WebRequestRequestCookieAction::GetName() const {
1050 switch (request_cookie_modification_->type) {
1051 case helpers::ADD:
1052 return keys::kAddRequestCookieType;
1053 case helpers::EDIT:
1054 return keys::kEditRequestCookieType;
1055 case helpers::REMOVE:
1056 return keys::kRemoveRequestCookieType;
1057 }
1058 NOTREACHED();
1059 return "";
1060 }
1061
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const1062 LinkedPtrEventResponseDelta WebRequestRequestCookieAction::CreateDelta(
1063 const WebRequestData& request_data,
1064 const std::string& extension_id,
1065 const base::Time& extension_install_time) const {
1066 CHECK(request_data.stage & stages());
1067 LinkedPtrEventResponseDelta result(
1068 new extension_web_request_api_helpers::EventResponseDelta(
1069 extension_id, extension_install_time));
1070 result->request_cookie_modifications.push_back(
1071 request_cookie_modification_);
1072 return result;
1073 }
1074
1075 //
1076 // WebRequestResponseCookieAction
1077 //
1078
WebRequestResponseCookieAction(linked_ptr<ResponseCookieModification> response_cookie_modification)1079 WebRequestResponseCookieAction::WebRequestResponseCookieAction(
1080 linked_ptr<ResponseCookieModification> response_cookie_modification)
1081 : WebRequestAction(ON_HEADERS_RECEIVED,
1082 ACTION_MODIFY_RESPONSE_COOKIE,
1083 std::numeric_limits<int>::min(),
1084 STRATEGY_DEFAULT),
1085 response_cookie_modification_(response_cookie_modification) {
1086 CHECK(response_cookie_modification_.get());
1087 }
1088
~WebRequestResponseCookieAction()1089 WebRequestResponseCookieAction::~WebRequestResponseCookieAction() {}
1090
Equals(const WebRequestAction * other) const1091 bool WebRequestResponseCookieAction::Equals(
1092 const WebRequestAction* other) const {
1093 if (!WebRequestAction::Equals(other))
1094 return false;
1095 const WebRequestResponseCookieAction* casted_other =
1096 static_cast<const WebRequestResponseCookieAction*>(other);
1097 return helpers::NullableEquals(
1098 response_cookie_modification_.get(),
1099 casted_other->response_cookie_modification_.get());
1100 }
1101
GetName() const1102 std::string WebRequestResponseCookieAction::GetName() const {
1103 switch (response_cookie_modification_->type) {
1104 case helpers::ADD:
1105 return keys::kAddResponseCookieType;
1106 case helpers::EDIT:
1107 return keys::kEditResponseCookieType;
1108 case helpers::REMOVE:
1109 return keys::kRemoveResponseCookieType;
1110 }
1111 NOTREACHED();
1112 return "";
1113 }
1114
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const1115 LinkedPtrEventResponseDelta WebRequestResponseCookieAction::CreateDelta(
1116 const WebRequestData& request_data,
1117 const std::string& extension_id,
1118 const base::Time& extension_install_time) const {
1119 CHECK(request_data.stage & stages());
1120 LinkedPtrEventResponseDelta result(
1121 new extension_web_request_api_helpers::EventResponseDelta(
1122 extension_id, extension_install_time));
1123 result->response_cookie_modifications.push_back(
1124 response_cookie_modification_);
1125 return result;
1126 }
1127
1128 //
1129 // WebRequestSendMessageToExtensionAction
1130 //
1131
WebRequestSendMessageToExtensionAction(const std::string & message)1132 WebRequestSendMessageToExtensionAction::WebRequestSendMessageToExtensionAction(
1133 const std::string& message)
1134 : WebRequestAction(ON_BEFORE_REQUEST | ON_BEFORE_SEND_HEADERS |
1135 ON_HEADERS_RECEIVED | ON_AUTH_REQUIRED,
1136 ACTION_SEND_MESSAGE_TO_EXTENSION,
1137 std::numeric_limits<int>::min(),
1138 STRATEGY_HOST),
1139 message_(message) {}
1140
1141 WebRequestSendMessageToExtensionAction::
~WebRequestSendMessageToExtensionAction()1142 ~WebRequestSendMessageToExtensionAction() {}
1143
Equals(const WebRequestAction * other) const1144 bool WebRequestSendMessageToExtensionAction::Equals(
1145 const WebRequestAction* other) const {
1146 if (!WebRequestAction::Equals(other))
1147 return false;
1148 const WebRequestSendMessageToExtensionAction* casted_other =
1149 static_cast<const WebRequestSendMessageToExtensionAction*>(other);
1150 return message_ == casted_other->message_;
1151 }
1152
GetName() const1153 std::string WebRequestSendMessageToExtensionAction::GetName() const {
1154 return keys::kSendMessageToExtensionType;
1155 }
1156
CreateDelta(const WebRequestData & request_data,const std::string & extension_id,const base::Time & extension_install_time) const1157 LinkedPtrEventResponseDelta WebRequestSendMessageToExtensionAction::CreateDelta(
1158 const WebRequestData& request_data,
1159 const std::string& extension_id,
1160 const base::Time& extension_install_time) const {
1161 CHECK(request_data.stage & stages());
1162 LinkedPtrEventResponseDelta result(
1163 new extension_web_request_api_helpers::EventResponseDelta(
1164 extension_id, extension_install_time));
1165 result->messages_to_extension.insert(message_);
1166 return result;
1167 }
1168
1169 } // namespace extensions
1170