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.
5 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h"
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 "content/public/common/url_constants.h"
22 #include "extensions/browser/info_map.h"
23 #include "extensions/common/error_utils.h"
24 #include "extensions/common/extension.h"
25 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
26 #include "net/url_request/url_request.h"
27 #include "third_party/re2/re2/re2.h"
29 namespace extensions
{
31 namespace helpers
= extension_web_request_api_helpers
;
32 namespace keys
= declarative_webrequest_constants
;
36 const char kIgnoreRulesRequiresParameterError
[] =
37 "IgnoreRules requires at least one parameter.";
39 const char kTransparentImageUrl
[] = "data:image/png;base64,iVBORw0KGgoAAAANSUh"
40 "EUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==";
41 const char kEmptyDocumentUrl
[] = "data:text/html,";
43 #define INPUT_FORMAT_VALIDATE(test) do { \
45 *bad_message = true; \
46 return scoped_refptr<const WebRequestAction>(NULL); \
50 scoped_ptr
<helpers::RequestCookie
> ParseRequestCookie(
51 const base::DictionaryValue
* dict
) {
52 scoped_ptr
<helpers::RequestCookie
> result(new helpers::RequestCookie
);
54 if (dict
->GetString(keys::kNameKey
, &tmp
))
55 result
->name
.reset(new std::string(tmp
));
56 if (dict
->GetString(keys::kValueKey
, &tmp
))
57 result
->value
.reset(new std::string(tmp
));
61 void ParseResponseCookieImpl(const base::DictionaryValue
* dict
,
62 helpers::ResponseCookie
* cookie
) {
63 std::string string_tmp
;
65 bool bool_tmp
= false;
66 if (dict
->GetString(keys::kNameKey
, &string_tmp
))
67 cookie
->name
.reset(new std::string(string_tmp
));
68 if (dict
->GetString(keys::kValueKey
, &string_tmp
))
69 cookie
->value
.reset(new std::string(string_tmp
));
70 if (dict
->GetString(keys::kExpiresKey
, &string_tmp
))
71 cookie
->expires
.reset(new std::string(string_tmp
));
72 if (dict
->GetInteger(keys::kMaxAgeKey
, &int_tmp
))
73 cookie
->max_age
.reset(new int(int_tmp
));
74 if (dict
->GetString(keys::kDomainKey
, &string_tmp
))
75 cookie
->domain
.reset(new std::string(string_tmp
));
76 if (dict
->GetString(keys::kPathKey
, &string_tmp
))
77 cookie
->path
.reset(new std::string(string_tmp
));
78 if (dict
->GetBoolean(keys::kSecureKey
, &bool_tmp
))
79 cookie
->secure
.reset(new bool(bool_tmp
));
80 if (dict
->GetBoolean(keys::kHttpOnlyKey
, &bool_tmp
))
81 cookie
->http_only
.reset(new bool(bool_tmp
));
84 scoped_ptr
<helpers::ResponseCookie
> ParseResponseCookie(
85 const base::DictionaryValue
* dict
) {
86 scoped_ptr
<helpers::ResponseCookie
> result(new helpers::ResponseCookie
);
87 ParseResponseCookieImpl(dict
, result
.get());
91 scoped_ptr
<helpers::FilterResponseCookie
> ParseFilterResponseCookie(
92 const base::DictionaryValue
* dict
) {
93 scoped_ptr
<helpers::FilterResponseCookie
> result(
94 new helpers::FilterResponseCookie
);
95 ParseResponseCookieImpl(dict
, result
.get());
98 bool bool_tmp
= false;
99 if (dict
->GetInteger(keys::kAgeUpperBoundKey
, &int_tmp
))
100 result
->age_upper_bound
.reset(new int(int_tmp
));
101 if (dict
->GetInteger(keys::kAgeLowerBoundKey
, &int_tmp
))
102 result
->age_lower_bound
.reset(new int(int_tmp
));
103 if (dict
->GetBoolean(keys::kSessionCookieKey
, &bool_tmp
))
104 result
->session_cookie
.reset(new bool(bool_tmp
));
105 return result
.Pass();
108 // Helper function for WebRequestActions that can be instantiated by just
109 // calling the constructor.
111 scoped_refptr
<const WebRequestAction
> CallConstructorFactoryMethod(
112 const std::string
& instance_type
,
113 const base::Value
* value
,
116 return scoped_refptr
<const WebRequestAction
>(new T
);
119 scoped_refptr
<const WebRequestAction
> CreateRedirectRequestAction(
120 const std::string
& instance_type
,
121 const base::Value
* value
,
124 const base::DictionaryValue
* dict
= NULL
;
125 CHECK(value
->GetAsDictionary(&dict
));
126 std::string redirect_url_string
;
127 INPUT_FORMAT_VALIDATE(
128 dict
->GetString(keys::kRedirectUrlKey
, &redirect_url_string
));
129 GURL
redirect_url(redirect_url_string
);
130 return scoped_refptr
<const WebRequestAction
>(
131 new WebRequestRedirectAction(redirect_url
));
134 scoped_refptr
<const WebRequestAction
> CreateRedirectRequestByRegExAction(
135 const std::string
& instance_type
,
136 const base::Value
* value
,
139 const base::DictionaryValue
* dict
= NULL
;
140 CHECK(value
->GetAsDictionary(&dict
));
143 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kFromKey
, &from
));
144 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kToKey
, &to
));
146 to
= WebRequestRedirectByRegExAction::PerlToRe2Style(to
);
148 RE2::Options options
;
149 options
.set_case_sensitive(false);
150 scoped_ptr
<RE2
> from_pattern(new RE2(from
, options
));
152 if (!from_pattern
->ok()) {
153 *error
= "Invalid pattern '" + from
+ "' -> '" + to
+ "'";
154 return scoped_refptr
<const WebRequestAction
>(NULL
);
156 return scoped_refptr
<const WebRequestAction
>(
157 new WebRequestRedirectByRegExAction(from_pattern
.Pass(), to
));
160 scoped_refptr
<const WebRequestAction
> CreateSetRequestHeaderAction(
161 const std::string
& instance_type
,
162 const base::Value
* json_value
,
165 const base::DictionaryValue
* dict
= NULL
;
166 CHECK(json_value
->GetAsDictionary(&dict
));
169 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kNameKey
, &name
));
170 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kValueKey
, &value
));
171 if (!helpers::IsValidHeaderName(name
)) {
172 *error
= extension_web_request_api_constants::kInvalidHeaderName
;
173 return scoped_refptr
<const WebRequestAction
>(NULL
);
175 if (!helpers::IsValidHeaderValue(value
)) {
176 *error
= ErrorUtils::FormatErrorMessage(
177 extension_web_request_api_constants::kInvalidHeaderValue
, name
);
178 return scoped_refptr
<const WebRequestAction
>(NULL
);
180 return scoped_refptr
<const WebRequestAction
>(
181 new WebRequestSetRequestHeaderAction(name
, value
));
184 scoped_refptr
<const WebRequestAction
> CreateRemoveRequestHeaderAction(
185 const std::string
& instance_type
,
186 const base::Value
* value
,
189 const base::DictionaryValue
* dict
= NULL
;
190 CHECK(value
->GetAsDictionary(&dict
));
192 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kNameKey
, &name
));
193 if (!helpers::IsValidHeaderName(name
)) {
194 *error
= extension_web_request_api_constants::kInvalidHeaderName
;
195 return scoped_refptr
<const WebRequestAction
>(NULL
);
197 return scoped_refptr
<const WebRequestAction
>(
198 new WebRequestRemoveRequestHeaderAction(name
));
201 scoped_refptr
<const WebRequestAction
> CreateAddResponseHeaderAction(
202 const std::string
& instance_type
,
203 const base::Value
* json_value
,
206 const base::DictionaryValue
* dict
= NULL
;
207 CHECK(json_value
->GetAsDictionary(&dict
));
210 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kNameKey
, &name
));
211 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kValueKey
, &value
));
212 if (!helpers::IsValidHeaderName(name
)) {
213 *error
= extension_web_request_api_constants::kInvalidHeaderName
;
214 return scoped_refptr
<const WebRequestAction
>(NULL
);
216 if (!helpers::IsValidHeaderValue(value
)) {
217 *error
= ErrorUtils::FormatErrorMessage(
218 extension_web_request_api_constants::kInvalidHeaderValue
, name
);
219 return scoped_refptr
<const WebRequestAction
>(NULL
);
221 return scoped_refptr
<const WebRequestAction
>(
222 new WebRequestAddResponseHeaderAction(name
, value
));
225 scoped_refptr
<const WebRequestAction
> CreateRemoveResponseHeaderAction(
226 const std::string
& instance_type
,
227 const base::Value
* json_value
,
230 const base::DictionaryValue
* dict
= NULL
;
231 CHECK(json_value
->GetAsDictionary(&dict
));
234 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kNameKey
, &name
));
235 bool has_value
= dict
->GetString(keys::kValueKey
, &value
);
236 if (!helpers::IsValidHeaderName(name
)) {
237 *error
= extension_web_request_api_constants::kInvalidHeaderName
;
238 return scoped_refptr
<const WebRequestAction
>(NULL
);
240 if (has_value
&& !helpers::IsValidHeaderValue(value
)) {
241 *error
= ErrorUtils::FormatErrorMessage(
242 extension_web_request_api_constants::kInvalidHeaderValue
, name
);
243 return scoped_refptr
<const WebRequestAction
>(NULL
);
245 return scoped_refptr
<const WebRequestAction
>(
246 new WebRequestRemoveResponseHeaderAction(name
, value
, has_value
));
249 scoped_refptr
<const WebRequestAction
> CreateIgnoreRulesAction(
250 const std::string
& instance_type
,
251 const base::Value
* value
,
254 const base::DictionaryValue
* dict
= NULL
;
255 CHECK(value
->GetAsDictionary(&dict
));
256 bool has_parameter
= false;
257 int minimum_priority
= std::numeric_limits
<int>::min();
258 std::string ignore_tag
;
259 if (dict
->HasKey(keys::kLowerPriorityThanKey
)) {
260 INPUT_FORMAT_VALIDATE(
261 dict
->GetInteger(keys::kLowerPriorityThanKey
, &minimum_priority
));
262 has_parameter
= true;
264 if (dict
->HasKey(keys::kHasTagKey
)) {
265 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kHasTagKey
, &ignore_tag
));
266 has_parameter
= true;
268 if (!has_parameter
) {
269 *error
= kIgnoreRulesRequiresParameterError
;
270 return scoped_refptr
<const WebRequestAction
>(NULL
);
272 return scoped_refptr
<const WebRequestAction
>(
273 new WebRequestIgnoreRulesAction(minimum_priority
, ignore_tag
));
276 scoped_refptr
<const WebRequestAction
> CreateRequestCookieAction(
277 const std::string
& instance_type
,
278 const base::Value
* value
,
281 using extension_web_request_api_helpers::RequestCookieModification
;
283 const base::DictionaryValue
* dict
= NULL
;
284 CHECK(value
->GetAsDictionary(&dict
));
286 linked_ptr
<RequestCookieModification
> modification(
287 new RequestCookieModification
);
289 // Get modification type.
290 if (instance_type
== keys::kAddRequestCookieType
)
291 modification
->type
= helpers::ADD
;
292 else if (instance_type
== keys::kEditRequestCookieType
)
293 modification
->type
= helpers::EDIT
;
294 else if (instance_type
== keys::kRemoveRequestCookieType
)
295 modification
->type
= helpers::REMOVE
;
297 INPUT_FORMAT_VALIDATE(false);
300 if (modification
->type
== helpers::EDIT
||
301 modification
->type
== helpers::REMOVE
) {
302 const base::DictionaryValue
* filter
= NULL
;
303 INPUT_FORMAT_VALIDATE(dict
->GetDictionary(keys::kFilterKey
, &filter
));
304 modification
->filter
= ParseRequestCookie(filter
);
308 if (modification
->type
== helpers::ADD
) {
309 const base::DictionaryValue
* value
= NULL
;
310 INPUT_FORMAT_VALIDATE(dict
->GetDictionary(keys::kCookieKey
, &value
));
311 modification
->modification
= ParseRequestCookie(value
);
312 } else if (modification
->type
== helpers::EDIT
) {
313 const base::DictionaryValue
* value
= NULL
;
314 INPUT_FORMAT_VALIDATE(dict
->GetDictionary(keys::kModificationKey
, &value
));
315 modification
->modification
= ParseRequestCookie(value
);
318 return scoped_refptr
<const WebRequestAction
>(
319 new WebRequestRequestCookieAction(modification
));
322 scoped_refptr
<const WebRequestAction
> CreateResponseCookieAction(
323 const std::string
& instance_type
,
324 const base::Value
* value
,
327 using extension_web_request_api_helpers::ResponseCookieModification
;
329 const base::DictionaryValue
* dict
= NULL
;
330 CHECK(value
->GetAsDictionary(&dict
));
332 linked_ptr
<ResponseCookieModification
> modification(
333 new ResponseCookieModification
);
335 // Get modification type.
336 if (instance_type
== keys::kAddResponseCookieType
)
337 modification
->type
= helpers::ADD
;
338 else if (instance_type
== keys::kEditResponseCookieType
)
339 modification
->type
= helpers::EDIT
;
340 else if (instance_type
== keys::kRemoveResponseCookieType
)
341 modification
->type
= helpers::REMOVE
;
343 INPUT_FORMAT_VALIDATE(false);
346 if (modification
->type
== helpers::EDIT
||
347 modification
->type
== helpers::REMOVE
) {
348 const base::DictionaryValue
* filter
= NULL
;
349 INPUT_FORMAT_VALIDATE(dict
->GetDictionary(keys::kFilterKey
, &filter
));
350 modification
->filter
= ParseFilterResponseCookie(filter
);
354 if (modification
->type
== helpers::ADD
) {
355 const base::DictionaryValue
* value
= NULL
;
356 INPUT_FORMAT_VALIDATE(dict
->GetDictionary(keys::kCookieKey
, &value
));
357 modification
->modification
= ParseResponseCookie(value
);
358 } else if (modification
->type
== helpers::EDIT
) {
359 const base::DictionaryValue
* value
= NULL
;
360 INPUT_FORMAT_VALIDATE(dict
->GetDictionary(keys::kModificationKey
, &value
));
361 modification
->modification
= ParseResponseCookie(value
);
364 return scoped_refptr
<const WebRequestAction
>(
365 new WebRequestResponseCookieAction(modification
));
368 scoped_refptr
<const WebRequestAction
> CreateSendMessageToExtensionAction(
369 const std::string
& name
,
370 const base::Value
* value
,
373 const base::DictionaryValue
* dict
= NULL
;
374 CHECK(value
->GetAsDictionary(&dict
));
376 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kMessageKey
, &message
));
377 return scoped_refptr
<const WebRequestAction
>(
378 new WebRequestSendMessageToExtensionAction(message
));
381 struct WebRequestActionFactory
{
382 DedupingFactory
<WebRequestAction
> factory
;
384 WebRequestActionFactory() : factory(5) {
385 factory
.RegisterFactoryMethod(
386 keys::kAddRequestCookieType
,
387 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
388 &CreateRequestCookieAction
);
389 factory
.RegisterFactoryMethod(
390 keys::kAddResponseCookieType
,
391 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
392 &CreateResponseCookieAction
);
393 factory
.RegisterFactoryMethod(
394 keys::kAddResponseHeaderType
,
395 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
396 &CreateAddResponseHeaderAction
);
397 factory
.RegisterFactoryMethod(
398 keys::kCancelRequestType
,
399 DedupingFactory
<WebRequestAction
>::IS_NOT_PARAMETERIZED
,
400 &CallConstructorFactoryMethod
<WebRequestCancelAction
>);
401 factory
.RegisterFactoryMethod(
402 keys::kEditRequestCookieType
,
403 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
404 &CreateRequestCookieAction
);
405 factory
.RegisterFactoryMethod(
406 keys::kEditResponseCookieType
,
407 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
408 &CreateResponseCookieAction
);
409 factory
.RegisterFactoryMethod(
410 keys::kRedirectByRegExType
,
411 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
412 &CreateRedirectRequestByRegExAction
);
413 factory
.RegisterFactoryMethod(
414 keys::kRedirectRequestType
,
415 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
416 &CreateRedirectRequestAction
);
417 factory
.RegisterFactoryMethod(
418 keys::kRedirectToTransparentImageType
,
419 DedupingFactory
<WebRequestAction
>::IS_NOT_PARAMETERIZED
,
420 &CallConstructorFactoryMethod
<
421 WebRequestRedirectToTransparentImageAction
>);
422 factory
.RegisterFactoryMethod(
423 keys::kRedirectToEmptyDocumentType
,
424 DedupingFactory
<WebRequestAction
>::IS_NOT_PARAMETERIZED
,
425 &CallConstructorFactoryMethod
<WebRequestRedirectToEmptyDocumentAction
>);
426 factory
.RegisterFactoryMethod(
427 keys::kRemoveRequestCookieType
,
428 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
429 &CreateRequestCookieAction
);
430 factory
.RegisterFactoryMethod(
431 keys::kRemoveResponseCookieType
,
432 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
433 &CreateResponseCookieAction
);
434 factory
.RegisterFactoryMethod(
435 keys::kSetRequestHeaderType
,
436 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
437 &CreateSetRequestHeaderAction
);
438 factory
.RegisterFactoryMethod(
439 keys::kRemoveRequestHeaderType
,
440 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
441 &CreateRemoveRequestHeaderAction
);
442 factory
.RegisterFactoryMethod(
443 keys::kRemoveResponseHeaderType
,
444 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
445 &CreateRemoveResponseHeaderAction
);
446 factory
.RegisterFactoryMethod(
447 keys::kIgnoreRulesType
,
448 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
449 &CreateIgnoreRulesAction
);
450 factory
.RegisterFactoryMethod(
451 keys::kSendMessageToExtensionType
,
452 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
453 &CreateSendMessageToExtensionAction
);
457 base::LazyInstance
<WebRequestActionFactory
>::Leaky
458 g_web_request_action_factory
= LAZY_INSTANCE_INITIALIZER
;
466 WebRequestAction::~WebRequestAction() {}
468 bool WebRequestAction::Equals(const WebRequestAction
* other
) const {
469 return type() == other
->type();
472 bool WebRequestAction::HasPermission(const InfoMap
* extension_info_map
,
473 const std::string
& extension_id
,
474 const net::URLRequest
* request
,
475 bool crosses_incognito
) const {
476 if (WebRequestPermissions::HideRequest(extension_info_map
, request
))
479 // In unit tests we don't have an extension_info_map object here and skip host
480 // permission checks.
481 if (!extension_info_map
)
484 WebRequestPermissions::HostPermissionsCheck permission_check
=
485 WebRequestPermissions::REQUIRE_ALL_URLS
;
486 switch (host_permissions_strategy()) {
487 case STRATEGY_DEFAULT
: // Default value is already set.
490 permission_check
= WebRequestPermissions::DO_NOT_CHECK_HOST
;
493 permission_check
= WebRequestPermissions::REQUIRE_HOST_PERMISSION
;
496 return WebRequestPermissions::CanExtensionAccessURL(
497 extension_info_map
, extension_id
, request
->url(), crosses_incognito
,
502 scoped_refptr
<const WebRequestAction
> WebRequestAction::Create(
503 const Extension
* extension
,
504 const base::Value
& json_action
,
508 *bad_message
= false;
510 const base::DictionaryValue
* action_dict
= NULL
;
511 INPUT_FORMAT_VALIDATE(json_action
.GetAsDictionary(&action_dict
));
513 std::string instance_type
;
514 INPUT_FORMAT_VALIDATE(
515 action_dict
->GetString(keys::kInstanceTypeKey
, &instance_type
));
517 WebRequestActionFactory
& factory
= g_web_request_action_factory
.Get();
518 return factory
.factory
.Instantiate(
519 instance_type
, action_dict
, error
, bad_message
);
522 void WebRequestAction::Apply(const std::string
& extension_id
,
523 base::Time extension_install_time
,
524 ApplyInfo
* apply_info
) const {
525 if (!HasPermission(apply_info
->extension_info_map
, extension_id
,
526 apply_info
->request_data
.request
,
527 apply_info
->crosses_incognito
))
529 if (stages() & apply_info
->request_data
.stage
) {
530 LinkedPtrEventResponseDelta delta
= CreateDelta(
531 apply_info
->request_data
, extension_id
, extension_install_time
);
533 apply_info
->deltas
->push_back(delta
);
534 if (type() == WebRequestAction::ACTION_IGNORE_RULES
) {
535 const WebRequestIgnoreRulesAction
* ignore_action
=
536 static_cast<const WebRequestIgnoreRulesAction
*>(this);
537 if (!ignore_action
->ignore_tag().empty())
538 apply_info
->ignored_tags
->insert(ignore_action
->ignore_tag());
543 WebRequestAction::WebRequestAction(int stages
,
545 int minimum_priority
,
546 HostPermissionsStrategy strategy
)
549 minimum_priority_(minimum_priority
),
550 host_permissions_strategy_(strategy
) {}
553 // WebRequestCancelAction
556 WebRequestCancelAction::WebRequestCancelAction()
557 : WebRequestAction(ON_BEFORE_REQUEST
| ON_BEFORE_SEND_HEADERS
|
558 ON_HEADERS_RECEIVED
| ON_AUTH_REQUIRED
,
559 ACTION_CANCEL_REQUEST
,
560 std::numeric_limits
<int>::min(),
563 WebRequestCancelAction::~WebRequestCancelAction() {}
565 std::string
WebRequestCancelAction::GetName() const {
566 return keys::kCancelRequestType
;
569 LinkedPtrEventResponseDelta
WebRequestCancelAction::CreateDelta(
570 const WebRequestData
& request_data
,
571 const std::string
& extension_id
,
572 const base::Time
& extension_install_time
) const {
573 CHECK(request_data
.stage
& stages());
574 LinkedPtrEventResponseDelta
result(
575 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
576 result
->cancel
= true;
581 // WebRequestRedirectAction
584 WebRequestRedirectAction::WebRequestRedirectAction(const GURL
& redirect_url
)
585 : WebRequestAction(ON_BEFORE_REQUEST
| ON_HEADERS_RECEIVED
,
586 ACTION_REDIRECT_REQUEST
,
587 std::numeric_limits
<int>::min(),
589 redirect_url_(redirect_url
) {}
591 WebRequestRedirectAction::~WebRequestRedirectAction() {}
593 bool WebRequestRedirectAction::Equals(const WebRequestAction
* other
) const {
594 return WebRequestAction::Equals(other
) &&
596 static_cast<const WebRequestRedirectAction
*>(other
)->redirect_url_
;
599 std::string
WebRequestRedirectAction::GetName() const {
600 return keys::kRedirectRequestType
;
603 LinkedPtrEventResponseDelta
WebRequestRedirectAction::CreateDelta(
604 const WebRequestData
& request_data
,
605 const std::string
& extension_id
,
606 const base::Time
& extension_install_time
) const {
607 CHECK(request_data
.stage
& stages());
608 if (request_data
.request
->url() == redirect_url_
)
609 return LinkedPtrEventResponseDelta(NULL
);
610 LinkedPtrEventResponseDelta
result(
611 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
612 result
->new_url
= redirect_url_
;
617 // WebRequestRedirectToTransparentImageAction
620 WebRequestRedirectToTransparentImageAction::
621 WebRequestRedirectToTransparentImageAction()
622 : WebRequestAction(ON_BEFORE_REQUEST
| ON_HEADERS_RECEIVED
,
623 ACTION_REDIRECT_TO_TRANSPARENT_IMAGE
,
624 std::numeric_limits
<int>::min(),
627 WebRequestRedirectToTransparentImageAction::
628 ~WebRequestRedirectToTransparentImageAction() {}
630 std::string
WebRequestRedirectToTransparentImageAction::GetName() const {
631 return keys::kRedirectToTransparentImageType
;
634 LinkedPtrEventResponseDelta
635 WebRequestRedirectToTransparentImageAction::CreateDelta(
636 const WebRequestData
& request_data
,
637 const std::string
& extension_id
,
638 const base::Time
& extension_install_time
) const {
639 CHECK(request_data
.stage
& stages());
640 LinkedPtrEventResponseDelta
result(
641 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
642 result
->new_url
= GURL(kTransparentImageUrl
);
647 // WebRequestRedirectToEmptyDocumentAction
650 WebRequestRedirectToEmptyDocumentAction::
651 WebRequestRedirectToEmptyDocumentAction()
652 : WebRequestAction(ON_BEFORE_REQUEST
| ON_HEADERS_RECEIVED
,
653 ACTION_REDIRECT_TO_EMPTY_DOCUMENT
,
654 std::numeric_limits
<int>::min(),
657 WebRequestRedirectToEmptyDocumentAction::
658 ~WebRequestRedirectToEmptyDocumentAction() {}
660 std::string
WebRequestRedirectToEmptyDocumentAction::GetName() const {
661 return keys::kRedirectToEmptyDocumentType
;
664 LinkedPtrEventResponseDelta
665 WebRequestRedirectToEmptyDocumentAction::CreateDelta(
666 const WebRequestData
& request_data
,
667 const std::string
& extension_id
,
668 const base::Time
& extension_install_time
) const {
669 CHECK(request_data
.stage
& stages());
670 LinkedPtrEventResponseDelta
result(
671 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
672 result
->new_url
= GURL(kEmptyDocumentUrl
);
677 // WebRequestRedirectByRegExAction
680 WebRequestRedirectByRegExAction::WebRequestRedirectByRegExAction(
681 scoped_ptr
<RE2
> from_pattern
,
682 const std::string
& to_pattern
)
683 : WebRequestAction(ON_BEFORE_REQUEST
| ON_HEADERS_RECEIVED
,
684 ACTION_REDIRECT_BY_REGEX_DOCUMENT
,
685 std::numeric_limits
<int>::min(),
687 from_pattern_(from_pattern
.Pass()),
688 to_pattern_(to_pattern
.data(), to_pattern
.size()) {}
690 WebRequestRedirectByRegExAction::~WebRequestRedirectByRegExAction() {}
692 // About the syntax of the two languages:
694 // ICU (Perl) states:
695 // $n The text of capture group n will be substituted for $n. n must be >= 0
696 // and not greater than the number of capture groups. A $ not followed by a
697 // digit has no special meaning, and will appear in the substitution text
699 // \ Treat the following character as a literal, suppressing any special
700 // meaning. Backslash escaping in substitution text is only required for
701 // '$' and '\', but may be used on any other character without bad effects.
703 // RE2, derived from RE2::Rewrite()
704 // \ May only be followed by a digit or another \. If followed by a single
705 // digit, both characters represent the respective capture group. If followed
706 // by another \, it is used as an escape sequence.
709 std::string
WebRequestRedirectByRegExAction::PerlToRe2Style(
710 const std::string
& perl
) {
711 std::string::const_iterator i
= perl
.begin();
713 while (i
!= perl
.end()) {
716 if (i
== perl
.end()) {
719 } else if (isdigit(*i
)) {
726 } else if (*i
== '\\') {
728 if (i
== perl
.end()) {
730 } else if (*i
== '$') {
732 } else if (*i
== '\\') {
745 bool WebRequestRedirectByRegExAction::Equals(
746 const WebRequestAction
* other
) const {
747 if (!WebRequestAction::Equals(other
))
749 const WebRequestRedirectByRegExAction
* casted_other
=
750 static_cast<const WebRequestRedirectByRegExAction
*>(other
);
751 return from_pattern_
->pattern() == casted_other
->from_pattern_
->pattern() &&
752 to_pattern_
== casted_other
->to_pattern_
;
755 std::string
WebRequestRedirectByRegExAction::GetName() const {
756 return keys::kRedirectByRegExType
;
759 LinkedPtrEventResponseDelta
WebRequestRedirectByRegExAction::CreateDelta(
760 const WebRequestData
& request_data
,
761 const std::string
& extension_id
,
762 const base::Time
& extension_install_time
) const {
763 CHECK(request_data
.stage
& stages());
764 CHECK(from_pattern_
.get());
766 const std::string
& old_url
= request_data
.request
->url().spec();
767 std::string new_url
= old_url
;
768 if (!RE2::Replace(&new_url
, *from_pattern_
, to_pattern_
) ||
769 new_url
== old_url
) {
770 return LinkedPtrEventResponseDelta(NULL
);
773 LinkedPtrEventResponseDelta
result(
774 new extension_web_request_api_helpers::EventResponseDelta(
775 extension_id
, extension_install_time
));
776 result
->new_url
= GURL(new_url
);
781 // WebRequestSetRequestHeaderAction
784 WebRequestSetRequestHeaderAction::WebRequestSetRequestHeaderAction(
785 const std::string
& name
,
786 const std::string
& value
)
787 : WebRequestAction(ON_BEFORE_SEND_HEADERS
,
788 ACTION_SET_REQUEST_HEADER
,
789 std::numeric_limits
<int>::min(),
794 WebRequestSetRequestHeaderAction::~WebRequestSetRequestHeaderAction() {}
796 bool WebRequestSetRequestHeaderAction::Equals(
797 const WebRequestAction
* other
) const {
798 if (!WebRequestAction::Equals(other
))
800 const WebRequestSetRequestHeaderAction
* casted_other
=
801 static_cast<const WebRequestSetRequestHeaderAction
*>(other
);
802 return name_
== casted_other
->name_
&& value_
== casted_other
->value_
;
805 std::string
WebRequestSetRequestHeaderAction::GetName() const {
806 return keys::kSetRequestHeaderType
;
810 LinkedPtrEventResponseDelta
811 WebRequestSetRequestHeaderAction::CreateDelta(
812 const WebRequestData
& request_data
,
813 const std::string
& extension_id
,
814 const base::Time
& extension_install_time
) const {
815 CHECK(request_data
.stage
& stages());
816 LinkedPtrEventResponseDelta
result(
817 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
818 result
->modified_request_headers
.SetHeader(name_
, value_
);
823 // WebRequestRemoveRequestHeaderAction
826 WebRequestRemoveRequestHeaderAction::WebRequestRemoveRequestHeaderAction(
827 const std::string
& name
)
828 : WebRequestAction(ON_BEFORE_SEND_HEADERS
,
829 ACTION_REMOVE_REQUEST_HEADER
,
830 std::numeric_limits
<int>::min(),
834 WebRequestRemoveRequestHeaderAction::~WebRequestRemoveRequestHeaderAction() {}
836 bool WebRequestRemoveRequestHeaderAction::Equals(
837 const WebRequestAction
* other
) const {
838 if (!WebRequestAction::Equals(other
))
840 const WebRequestRemoveRequestHeaderAction
* casted_other
=
841 static_cast<const WebRequestRemoveRequestHeaderAction
*>(other
);
842 return name_
== casted_other
->name_
;
845 std::string
WebRequestRemoveRequestHeaderAction::GetName() const {
846 return keys::kRemoveRequestHeaderType
;
849 LinkedPtrEventResponseDelta
850 WebRequestRemoveRequestHeaderAction::CreateDelta(
851 const WebRequestData
& request_data
,
852 const std::string
& extension_id
,
853 const base::Time
& extension_install_time
) const {
854 CHECK(request_data
.stage
& stages());
855 LinkedPtrEventResponseDelta
result(
856 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
857 result
->deleted_request_headers
.push_back(name_
);
862 // WebRequestAddResponseHeaderAction
865 WebRequestAddResponseHeaderAction::WebRequestAddResponseHeaderAction(
866 const std::string
& name
,
867 const std::string
& value
)
868 : WebRequestAction(ON_HEADERS_RECEIVED
,
869 ACTION_ADD_RESPONSE_HEADER
,
870 std::numeric_limits
<int>::min(),
875 WebRequestAddResponseHeaderAction::~WebRequestAddResponseHeaderAction() {}
877 bool WebRequestAddResponseHeaderAction::Equals(
878 const WebRequestAction
* other
) const {
879 if (!WebRequestAction::Equals(other
))
881 const WebRequestAddResponseHeaderAction
* casted_other
=
882 static_cast<const WebRequestAddResponseHeaderAction
*>(other
);
883 return name_
== casted_other
->name_
&& value_
== casted_other
->value_
;
886 std::string
WebRequestAddResponseHeaderAction::GetName() const {
887 return keys::kAddResponseHeaderType
;
890 LinkedPtrEventResponseDelta
891 WebRequestAddResponseHeaderAction::CreateDelta(
892 const WebRequestData
& request_data
,
893 const std::string
& extension_id
,
894 const base::Time
& extension_install_time
) const {
895 CHECK(request_data
.stage
& stages());
896 const net::HttpResponseHeaders
* headers
=
897 request_data
.original_response_headers
;
899 return LinkedPtrEventResponseDelta(NULL
);
901 // Don't generate the header if it exists already.
902 if (headers
->HasHeaderValue(name_
, value_
))
903 return LinkedPtrEventResponseDelta(NULL
);
905 LinkedPtrEventResponseDelta
result(
906 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
907 result
->added_response_headers
.push_back(make_pair(name_
, value_
));
912 // WebRequestRemoveResponseHeaderAction
915 WebRequestRemoveResponseHeaderAction::WebRequestRemoveResponseHeaderAction(
916 const std::string
& name
,
917 const std::string
& value
,
919 : WebRequestAction(ON_HEADERS_RECEIVED
,
920 ACTION_REMOVE_RESPONSE_HEADER
,
921 std::numeric_limits
<int>::min(),
925 has_value_(has_value
) {}
927 WebRequestRemoveResponseHeaderAction::~WebRequestRemoveResponseHeaderAction() {}
929 bool WebRequestRemoveResponseHeaderAction::Equals(
930 const WebRequestAction
* other
) const {
931 if (!WebRequestAction::Equals(other
))
933 const WebRequestRemoveResponseHeaderAction
* casted_other
=
934 static_cast<const WebRequestRemoveResponseHeaderAction
*>(other
);
935 return name_
== casted_other
->name_
&& value_
== casted_other
->value_
&&
936 has_value_
== casted_other
->has_value_
;
939 std::string
WebRequestRemoveResponseHeaderAction::GetName() const {
940 return keys::kRemoveResponseHeaderType
;
943 LinkedPtrEventResponseDelta
944 WebRequestRemoveResponseHeaderAction::CreateDelta(
945 const WebRequestData
& request_data
,
946 const std::string
& extension_id
,
947 const base::Time
& extension_install_time
) const {
948 CHECK(request_data
.stage
& stages());
949 const net::HttpResponseHeaders
* headers
=
950 request_data
.original_response_headers
;
952 return LinkedPtrEventResponseDelta(NULL
);
954 LinkedPtrEventResponseDelta
result(
955 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
957 std::string current_value
;
958 while (headers
->EnumerateHeader(&iter
, name_
, ¤t_value
)) {
960 (current_value
.size() != value_
.size() ||
961 !std::equal(current_value
.begin(), current_value
.end(),
963 base::CaseInsensitiveCompare
<char>()))) {
966 result
->deleted_response_headers
.push_back(make_pair(name_
, current_value
));
972 // WebRequestIgnoreRulesAction
975 WebRequestIgnoreRulesAction::WebRequestIgnoreRulesAction(
976 int minimum_priority
,
977 const std::string
& ignore_tag
)
978 : WebRequestAction(ON_BEFORE_REQUEST
| ON_BEFORE_SEND_HEADERS
|
979 ON_HEADERS_RECEIVED
| ON_AUTH_REQUIRED
,
983 ignore_tag_(ignore_tag
) {}
985 WebRequestIgnoreRulesAction::~WebRequestIgnoreRulesAction() {}
987 bool WebRequestIgnoreRulesAction::Equals(const WebRequestAction
* other
) const {
988 if (!WebRequestAction::Equals(other
))
990 const WebRequestIgnoreRulesAction
* casted_other
=
991 static_cast<const WebRequestIgnoreRulesAction
*>(other
);
992 return minimum_priority() == casted_other
->minimum_priority() &&
993 ignore_tag_
== casted_other
->ignore_tag_
;
996 std::string
WebRequestIgnoreRulesAction::GetName() const {
997 return keys::kIgnoreRulesType
;
1000 LinkedPtrEventResponseDelta
WebRequestIgnoreRulesAction::CreateDelta(
1001 const WebRequestData
& request_data
,
1002 const std::string
& extension_id
,
1003 const base::Time
& extension_install_time
) const {
1004 CHECK(request_data
.stage
& stages());
1005 return LinkedPtrEventResponseDelta(NULL
);
1009 // WebRequestRequestCookieAction
1012 WebRequestRequestCookieAction::WebRequestRequestCookieAction(
1013 linked_ptr
<RequestCookieModification
> request_cookie_modification
)
1014 : WebRequestAction(ON_BEFORE_SEND_HEADERS
,
1015 ACTION_MODIFY_REQUEST_COOKIE
,
1016 std::numeric_limits
<int>::min(),
1018 request_cookie_modification_(request_cookie_modification
) {
1019 CHECK(request_cookie_modification_
.get());
1022 WebRequestRequestCookieAction::~WebRequestRequestCookieAction() {}
1024 bool WebRequestRequestCookieAction::Equals(
1025 const WebRequestAction
* other
) const {
1026 if (!WebRequestAction::Equals(other
))
1028 const WebRequestRequestCookieAction
* casted_other
=
1029 static_cast<const WebRequestRequestCookieAction
*>(other
);
1030 return helpers::NullableEquals(
1031 request_cookie_modification_
.get(),
1032 casted_other
->request_cookie_modification_
.get());
1035 std::string
WebRequestRequestCookieAction::GetName() const {
1036 switch (request_cookie_modification_
->type
) {
1038 return keys::kAddRequestCookieType
;
1040 return keys::kEditRequestCookieType
;
1041 case helpers::REMOVE
:
1042 return keys::kRemoveRequestCookieType
;
1048 LinkedPtrEventResponseDelta
WebRequestRequestCookieAction::CreateDelta(
1049 const WebRequestData
& request_data
,
1050 const std::string
& extension_id
,
1051 const base::Time
& extension_install_time
) const {
1052 CHECK(request_data
.stage
& stages());
1053 LinkedPtrEventResponseDelta
result(
1054 new extension_web_request_api_helpers::EventResponseDelta(
1055 extension_id
, extension_install_time
));
1056 result
->request_cookie_modifications
.push_back(
1057 request_cookie_modification_
);
1062 // WebRequestResponseCookieAction
1065 WebRequestResponseCookieAction::WebRequestResponseCookieAction(
1066 linked_ptr
<ResponseCookieModification
> response_cookie_modification
)
1067 : WebRequestAction(ON_HEADERS_RECEIVED
,
1068 ACTION_MODIFY_RESPONSE_COOKIE
,
1069 std::numeric_limits
<int>::min(),
1071 response_cookie_modification_(response_cookie_modification
) {
1072 CHECK(response_cookie_modification_
.get());
1075 WebRequestResponseCookieAction::~WebRequestResponseCookieAction() {}
1077 bool WebRequestResponseCookieAction::Equals(
1078 const WebRequestAction
* other
) const {
1079 if (!WebRequestAction::Equals(other
))
1081 const WebRequestResponseCookieAction
* casted_other
=
1082 static_cast<const WebRequestResponseCookieAction
*>(other
);
1083 return helpers::NullableEquals(
1084 response_cookie_modification_
.get(),
1085 casted_other
->response_cookie_modification_
.get());
1088 std::string
WebRequestResponseCookieAction::GetName() const {
1089 switch (response_cookie_modification_
->type
) {
1091 return keys::kAddResponseCookieType
;
1093 return keys::kEditResponseCookieType
;
1094 case helpers::REMOVE
:
1095 return keys::kRemoveResponseCookieType
;
1101 LinkedPtrEventResponseDelta
WebRequestResponseCookieAction::CreateDelta(
1102 const WebRequestData
& request_data
,
1103 const std::string
& extension_id
,
1104 const base::Time
& extension_install_time
) const {
1105 CHECK(request_data
.stage
& stages());
1106 LinkedPtrEventResponseDelta
result(
1107 new extension_web_request_api_helpers::EventResponseDelta(
1108 extension_id
, extension_install_time
));
1109 result
->response_cookie_modifications
.push_back(
1110 response_cookie_modification_
);
1115 // WebRequestSendMessageToExtensionAction
1118 WebRequestSendMessageToExtensionAction::WebRequestSendMessageToExtensionAction(
1119 const std::string
& message
)
1120 : WebRequestAction(ON_BEFORE_REQUEST
| ON_BEFORE_SEND_HEADERS
|
1121 ON_HEADERS_RECEIVED
| ON_AUTH_REQUIRED
,
1122 ACTION_SEND_MESSAGE_TO_EXTENSION
,
1123 std::numeric_limits
<int>::min(),
1125 message_(message
) {}
1127 WebRequestSendMessageToExtensionAction::
1128 ~WebRequestSendMessageToExtensionAction() {}
1130 bool WebRequestSendMessageToExtensionAction::Equals(
1131 const WebRequestAction
* other
) const {
1132 if (!WebRequestAction::Equals(other
))
1134 const WebRequestSendMessageToExtensionAction
* casted_other
=
1135 static_cast<const WebRequestSendMessageToExtensionAction
*>(other
);
1136 return message_
== casted_other
->message_
;
1139 std::string
WebRequestSendMessageToExtensionAction::GetName() const {
1140 return keys::kSendMessageToExtensionType
;
1143 LinkedPtrEventResponseDelta
WebRequestSendMessageToExtensionAction::CreateDelta(
1144 const WebRequestData
& request_data
,
1145 const std::string
& extension_id
,
1146 const base::Time
& extension_install_time
) const {
1147 CHECK(request_data
.stage
& stages());
1148 LinkedPtrEventResponseDelta
result(
1149 new extension_web_request_api_helpers::EventResponseDelta(
1150 extension_id
, extension_install_time
));
1151 result
->messages_to_extension
.insert(message_
);
1155 } // namespace extensions