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 "extensions/browser/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 "content/public/browser/resource_request_info.h"
15 #include "content/public/common/url_constants.h"
16 #include "extensions/browser/api/declarative/deduping_factory.h"
17 #include "extensions/browser/api/declarative_webrequest/request_stage.h"
18 #include "extensions/browser/api/declarative_webrequest/webrequest_condition.h"
19 #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
20 #include "extensions/browser/api/web_request/web_request_api_constants.h"
21 #include "extensions/browser/api/web_request/web_request_api_helpers.h"
22 #include "extensions/browser/api/web_request/web_request_permissions.h"
23 #include "extensions/browser/guest_view/web_view/web_view_renderer_state.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/http/http_util.h"
29 #include "net/url_request/url_request.h"
30 #include "third_party/re2/re2/re2.h"
32 using content::ResourceRequestInfo
;
34 namespace extensions
{
36 namespace helpers
= extension_web_request_api_helpers
;
37 namespace keys
= declarative_webrequest_constants
;
41 const char kIgnoreRulesRequiresParameterError
[] =
42 "IgnoreRules requires at least one parameter.";
44 const char kTransparentImageUrl
[] = "data:image/png;base64,iVBORw0KGgoAAAANSUh"
45 "EUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==";
46 const char kEmptyDocumentUrl
[] = "data:text/html,";
48 #define INPUT_FORMAT_VALIDATE(test) do { \
50 *bad_message = true; \
51 return scoped_refptr<const WebRequestAction>(NULL); \
55 scoped_ptr
<helpers::RequestCookie
> ParseRequestCookie(
56 const base::DictionaryValue
* dict
) {
57 scoped_ptr
<helpers::RequestCookie
> result(new helpers::RequestCookie
);
59 if (dict
->GetString(keys::kNameKey
, &tmp
))
60 result
->name
.reset(new std::string(tmp
));
61 if (dict
->GetString(keys::kValueKey
, &tmp
))
62 result
->value
.reset(new std::string(tmp
));
66 void ParseResponseCookieImpl(const base::DictionaryValue
* dict
,
67 helpers::ResponseCookie
* cookie
) {
68 std::string string_tmp
;
70 bool bool_tmp
= false;
71 if (dict
->GetString(keys::kNameKey
, &string_tmp
))
72 cookie
->name
.reset(new std::string(string_tmp
));
73 if (dict
->GetString(keys::kValueKey
, &string_tmp
))
74 cookie
->value
.reset(new std::string(string_tmp
));
75 if (dict
->GetString(keys::kExpiresKey
, &string_tmp
))
76 cookie
->expires
.reset(new std::string(string_tmp
));
77 if (dict
->GetInteger(keys::kMaxAgeKey
, &int_tmp
))
78 cookie
->max_age
.reset(new int(int_tmp
));
79 if (dict
->GetString(keys::kDomainKey
, &string_tmp
))
80 cookie
->domain
.reset(new std::string(string_tmp
));
81 if (dict
->GetString(keys::kPathKey
, &string_tmp
))
82 cookie
->path
.reset(new std::string(string_tmp
));
83 if (dict
->GetBoolean(keys::kSecureKey
, &bool_tmp
))
84 cookie
->secure
.reset(new bool(bool_tmp
));
85 if (dict
->GetBoolean(keys::kHttpOnlyKey
, &bool_tmp
))
86 cookie
->http_only
.reset(new bool(bool_tmp
));
89 scoped_ptr
<helpers::ResponseCookie
> ParseResponseCookie(
90 const base::DictionaryValue
* dict
) {
91 scoped_ptr
<helpers::ResponseCookie
> result(new helpers::ResponseCookie
);
92 ParseResponseCookieImpl(dict
, result
.get());
96 scoped_ptr
<helpers::FilterResponseCookie
> ParseFilterResponseCookie(
97 const base::DictionaryValue
* dict
) {
98 scoped_ptr
<helpers::FilterResponseCookie
> result(
99 new helpers::FilterResponseCookie
);
100 ParseResponseCookieImpl(dict
, result
.get());
103 bool bool_tmp
= false;
104 if (dict
->GetInteger(keys::kAgeUpperBoundKey
, &int_tmp
))
105 result
->age_upper_bound
.reset(new int(int_tmp
));
106 if (dict
->GetInteger(keys::kAgeLowerBoundKey
, &int_tmp
))
107 result
->age_lower_bound
.reset(new int(int_tmp
));
108 if (dict
->GetBoolean(keys::kSessionCookieKey
, &bool_tmp
))
109 result
->session_cookie
.reset(new bool(bool_tmp
));
110 return result
.Pass();
113 // Helper function for WebRequestActions that can be instantiated by just
114 // calling the constructor.
116 scoped_refptr
<const WebRequestAction
> CallConstructorFactoryMethod(
117 const std::string
& instance_type
,
118 const base::Value
* value
,
121 return scoped_refptr
<const WebRequestAction
>(new T
);
124 scoped_refptr
<const WebRequestAction
> CreateRedirectRequestAction(
125 const std::string
& instance_type
,
126 const base::Value
* value
,
129 const base::DictionaryValue
* dict
= NULL
;
130 CHECK(value
->GetAsDictionary(&dict
));
131 std::string redirect_url_string
;
132 INPUT_FORMAT_VALIDATE(
133 dict
->GetString(keys::kRedirectUrlKey
, &redirect_url_string
));
134 GURL
redirect_url(redirect_url_string
);
135 return scoped_refptr
<const WebRequestAction
>(
136 new WebRequestRedirectAction(redirect_url
));
139 scoped_refptr
<const WebRequestAction
> CreateRedirectRequestByRegExAction(
140 const std::string
& instance_type
,
141 const base::Value
* value
,
144 const base::DictionaryValue
* dict
= NULL
;
145 CHECK(value
->GetAsDictionary(&dict
));
148 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kFromKey
, &from
));
149 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kToKey
, &to
));
151 to
= WebRequestRedirectByRegExAction::PerlToRe2Style(to
);
153 RE2::Options options
;
154 options
.set_case_sensitive(false);
155 scoped_ptr
<RE2
> from_pattern(new RE2(from
, options
));
157 if (!from_pattern
->ok()) {
158 *error
= "Invalid pattern '" + from
+ "' -> '" + to
+ "'";
159 return scoped_refptr
<const WebRequestAction
>(NULL
);
161 return scoped_refptr
<const WebRequestAction
>(
162 new WebRequestRedirectByRegExAction(from_pattern
.Pass(), to
));
165 scoped_refptr
<const WebRequestAction
> CreateSetRequestHeaderAction(
166 const std::string
& instance_type
,
167 const base::Value
* json_value
,
170 const base::DictionaryValue
* dict
= NULL
;
171 CHECK(json_value
->GetAsDictionary(&dict
));
174 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kNameKey
, &name
));
175 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kValueKey
, &value
));
176 if (!net::HttpUtil::IsValidHeaderName(name
)) {
177 *error
= extension_web_request_api_constants::kInvalidHeaderName
;
178 return scoped_refptr
<const WebRequestAction
>(NULL
);
180 if (!net::HttpUtil::IsValidHeaderValue(value
)) {
181 *error
= ErrorUtils::FormatErrorMessage(
182 extension_web_request_api_constants::kInvalidHeaderValue
, name
);
183 return scoped_refptr
<const WebRequestAction
>(NULL
);
185 return scoped_refptr
<const WebRequestAction
>(
186 new WebRequestSetRequestHeaderAction(name
, value
));
189 scoped_refptr
<const WebRequestAction
> CreateRemoveRequestHeaderAction(
190 const std::string
& instance_type
,
191 const base::Value
* value
,
194 const base::DictionaryValue
* dict
= NULL
;
195 CHECK(value
->GetAsDictionary(&dict
));
197 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kNameKey
, &name
));
198 if (!net::HttpUtil::IsValidHeaderName(name
)) {
199 *error
= extension_web_request_api_constants::kInvalidHeaderName
;
200 return scoped_refptr
<const WebRequestAction
>(NULL
);
202 return scoped_refptr
<const WebRequestAction
>(
203 new WebRequestRemoveRequestHeaderAction(name
));
206 scoped_refptr
<const WebRequestAction
> CreateAddResponseHeaderAction(
207 const std::string
& instance_type
,
208 const base::Value
* json_value
,
211 const base::DictionaryValue
* dict
= NULL
;
212 CHECK(json_value
->GetAsDictionary(&dict
));
215 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kNameKey
, &name
));
216 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kValueKey
, &value
));
217 if (!net::HttpUtil::IsValidHeaderName(name
)) {
218 *error
= extension_web_request_api_constants::kInvalidHeaderName
;
219 return scoped_refptr
<const WebRequestAction
>(NULL
);
221 if (!net::HttpUtil::IsValidHeaderValue(value
)) {
222 *error
= ErrorUtils::FormatErrorMessage(
223 extension_web_request_api_constants::kInvalidHeaderValue
, name
);
224 return scoped_refptr
<const WebRequestAction
>(NULL
);
226 return scoped_refptr
<const WebRequestAction
>(
227 new WebRequestAddResponseHeaderAction(name
, value
));
230 scoped_refptr
<const WebRequestAction
> CreateRemoveResponseHeaderAction(
231 const std::string
& instance_type
,
232 const base::Value
* json_value
,
235 const base::DictionaryValue
* dict
= NULL
;
236 CHECK(json_value
->GetAsDictionary(&dict
));
239 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kNameKey
, &name
));
240 bool has_value
= dict
->GetString(keys::kValueKey
, &value
);
241 if (!net::HttpUtil::IsValidHeaderName(name
)) {
242 *error
= extension_web_request_api_constants::kInvalidHeaderName
;
243 return scoped_refptr
<const WebRequestAction
>(NULL
);
245 if (has_value
&& !net::HttpUtil::IsValidHeaderValue(value
)) {
246 *error
= ErrorUtils::FormatErrorMessage(
247 extension_web_request_api_constants::kInvalidHeaderValue
, name
);
248 return scoped_refptr
<const WebRequestAction
>(NULL
);
250 return scoped_refptr
<const WebRequestAction
>(
251 new WebRequestRemoveResponseHeaderAction(name
, value
, has_value
));
254 scoped_refptr
<const WebRequestAction
> CreateIgnoreRulesAction(
255 const std::string
& instance_type
,
256 const base::Value
* value
,
259 const base::DictionaryValue
* dict
= NULL
;
260 CHECK(value
->GetAsDictionary(&dict
));
261 bool has_parameter
= false;
262 int minimum_priority
= std::numeric_limits
<int>::min();
263 std::string ignore_tag
;
264 if (dict
->HasKey(keys::kLowerPriorityThanKey
)) {
265 INPUT_FORMAT_VALIDATE(
266 dict
->GetInteger(keys::kLowerPriorityThanKey
, &minimum_priority
));
267 has_parameter
= true;
269 if (dict
->HasKey(keys::kHasTagKey
)) {
270 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kHasTagKey
, &ignore_tag
));
271 has_parameter
= true;
273 if (!has_parameter
) {
274 *error
= kIgnoreRulesRequiresParameterError
;
275 return scoped_refptr
<const WebRequestAction
>(NULL
);
277 return scoped_refptr
<const WebRequestAction
>(
278 new WebRequestIgnoreRulesAction(minimum_priority
, ignore_tag
));
281 scoped_refptr
<const WebRequestAction
> CreateRequestCookieAction(
282 const std::string
& instance_type
,
283 const base::Value
* value
,
286 using extension_web_request_api_helpers::RequestCookieModification
;
288 const base::DictionaryValue
* dict
= NULL
;
289 CHECK(value
->GetAsDictionary(&dict
));
291 linked_ptr
<RequestCookieModification
> modification(
292 new RequestCookieModification
);
294 // Get modification type.
295 if (instance_type
== keys::kAddRequestCookieType
)
296 modification
->type
= helpers::ADD
;
297 else if (instance_type
== keys::kEditRequestCookieType
)
298 modification
->type
= helpers::EDIT
;
299 else if (instance_type
== keys::kRemoveRequestCookieType
)
300 modification
->type
= helpers::REMOVE
;
302 INPUT_FORMAT_VALIDATE(false);
305 if (modification
->type
== helpers::EDIT
||
306 modification
->type
== helpers::REMOVE
) {
307 const base::DictionaryValue
* filter
= NULL
;
308 INPUT_FORMAT_VALIDATE(dict
->GetDictionary(keys::kFilterKey
, &filter
));
309 modification
->filter
= ParseRequestCookie(filter
);
313 if (modification
->type
== helpers::ADD
) {
314 const base::DictionaryValue
* value
= NULL
;
315 INPUT_FORMAT_VALIDATE(dict
->GetDictionary(keys::kCookieKey
, &value
));
316 modification
->modification
= ParseRequestCookie(value
);
317 } else if (modification
->type
== helpers::EDIT
) {
318 const base::DictionaryValue
* value
= NULL
;
319 INPUT_FORMAT_VALIDATE(dict
->GetDictionary(keys::kModificationKey
, &value
));
320 modification
->modification
= ParseRequestCookie(value
);
323 return scoped_refptr
<const WebRequestAction
>(
324 new WebRequestRequestCookieAction(modification
));
327 scoped_refptr
<const WebRequestAction
> CreateResponseCookieAction(
328 const std::string
& instance_type
,
329 const base::Value
* value
,
332 using extension_web_request_api_helpers::ResponseCookieModification
;
334 const base::DictionaryValue
* dict
= NULL
;
335 CHECK(value
->GetAsDictionary(&dict
));
337 linked_ptr
<ResponseCookieModification
> modification(
338 new ResponseCookieModification
);
340 // Get modification type.
341 if (instance_type
== keys::kAddResponseCookieType
)
342 modification
->type
= helpers::ADD
;
343 else if (instance_type
== keys::kEditResponseCookieType
)
344 modification
->type
= helpers::EDIT
;
345 else if (instance_type
== keys::kRemoveResponseCookieType
)
346 modification
->type
= helpers::REMOVE
;
348 INPUT_FORMAT_VALIDATE(false);
351 if (modification
->type
== helpers::EDIT
||
352 modification
->type
== helpers::REMOVE
) {
353 const base::DictionaryValue
* filter
= NULL
;
354 INPUT_FORMAT_VALIDATE(dict
->GetDictionary(keys::kFilterKey
, &filter
));
355 modification
->filter
= ParseFilterResponseCookie(filter
);
359 if (modification
->type
== helpers::ADD
) {
360 const base::DictionaryValue
* value
= NULL
;
361 INPUT_FORMAT_VALIDATE(dict
->GetDictionary(keys::kCookieKey
, &value
));
362 modification
->modification
= ParseResponseCookie(value
);
363 } else if (modification
->type
== helpers::EDIT
) {
364 const base::DictionaryValue
* value
= NULL
;
365 INPUT_FORMAT_VALIDATE(dict
->GetDictionary(keys::kModificationKey
, &value
));
366 modification
->modification
= ParseResponseCookie(value
);
369 return scoped_refptr
<const WebRequestAction
>(
370 new WebRequestResponseCookieAction(modification
));
373 scoped_refptr
<const WebRequestAction
> CreateSendMessageToExtensionAction(
374 const std::string
& name
,
375 const base::Value
* value
,
378 const base::DictionaryValue
* dict
= NULL
;
379 CHECK(value
->GetAsDictionary(&dict
));
381 INPUT_FORMAT_VALIDATE(dict
->GetString(keys::kMessageKey
, &message
));
382 return scoped_refptr
<const WebRequestAction
>(
383 new WebRequestSendMessageToExtensionAction(message
));
386 struct WebRequestActionFactory
{
387 DedupingFactory
<WebRequestAction
> factory
;
389 WebRequestActionFactory() : factory(5) {
390 factory
.RegisterFactoryMethod(
391 keys::kAddRequestCookieType
,
392 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
393 &CreateRequestCookieAction
);
394 factory
.RegisterFactoryMethod(
395 keys::kAddResponseCookieType
,
396 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
397 &CreateResponseCookieAction
);
398 factory
.RegisterFactoryMethod(
399 keys::kAddResponseHeaderType
,
400 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
401 &CreateAddResponseHeaderAction
);
402 factory
.RegisterFactoryMethod(
403 keys::kCancelRequestType
,
404 DedupingFactory
<WebRequestAction
>::IS_NOT_PARAMETERIZED
,
405 &CallConstructorFactoryMethod
<WebRequestCancelAction
>);
406 factory
.RegisterFactoryMethod(
407 keys::kEditRequestCookieType
,
408 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
409 &CreateRequestCookieAction
);
410 factory
.RegisterFactoryMethod(
411 keys::kEditResponseCookieType
,
412 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
413 &CreateResponseCookieAction
);
414 factory
.RegisterFactoryMethod(
415 keys::kRedirectByRegExType
,
416 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
417 &CreateRedirectRequestByRegExAction
);
418 factory
.RegisterFactoryMethod(
419 keys::kRedirectRequestType
,
420 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
421 &CreateRedirectRequestAction
);
422 factory
.RegisterFactoryMethod(
423 keys::kRedirectToTransparentImageType
,
424 DedupingFactory
<WebRequestAction
>::IS_NOT_PARAMETERIZED
,
425 &CallConstructorFactoryMethod
<
426 WebRequestRedirectToTransparentImageAction
>);
427 factory
.RegisterFactoryMethod(
428 keys::kRedirectToEmptyDocumentType
,
429 DedupingFactory
<WebRequestAction
>::IS_NOT_PARAMETERIZED
,
430 &CallConstructorFactoryMethod
<WebRequestRedirectToEmptyDocumentAction
>);
431 factory
.RegisterFactoryMethod(
432 keys::kRemoveRequestCookieType
,
433 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
434 &CreateRequestCookieAction
);
435 factory
.RegisterFactoryMethod(
436 keys::kRemoveResponseCookieType
,
437 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
438 &CreateResponseCookieAction
);
439 factory
.RegisterFactoryMethod(
440 keys::kSetRequestHeaderType
,
441 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
442 &CreateSetRequestHeaderAction
);
443 factory
.RegisterFactoryMethod(
444 keys::kRemoveRequestHeaderType
,
445 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
446 &CreateRemoveRequestHeaderAction
);
447 factory
.RegisterFactoryMethod(
448 keys::kRemoveResponseHeaderType
,
449 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
450 &CreateRemoveResponseHeaderAction
);
451 factory
.RegisterFactoryMethod(
452 keys::kIgnoreRulesType
,
453 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
454 &CreateIgnoreRulesAction
);
455 factory
.RegisterFactoryMethod(
456 keys::kSendMessageToExtensionType
,
457 DedupingFactory
<WebRequestAction
>::IS_PARAMETERIZED
,
458 &CreateSendMessageToExtensionAction
);
462 base::LazyInstance
<WebRequestActionFactory
>::Leaky
463 g_web_request_action_factory
= LAZY_INSTANCE_INITIALIZER
;
471 WebRequestAction::~WebRequestAction() {}
473 bool WebRequestAction::Equals(const WebRequestAction
* other
) const {
474 return type() == other
->type();
477 bool WebRequestAction::HasPermission(const InfoMap
* extension_info_map
,
478 const std::string
& extension_id
,
479 const net::URLRequest
* request
,
480 bool crosses_incognito
) const {
481 if (WebRequestPermissions::HideRequest(extension_info_map
, request
))
484 // In unit tests we don't have an extension_info_map object here and skip host
485 // permission checks.
486 if (!extension_info_map
)
489 const ResourceRequestInfo
* info
= ResourceRequestInfo::ForRequest(request
);
490 int process_id
= info
? info
->GetChildID() : 0;
492 // The embedder can always access all hosts from within a <webview>.
493 // The same is not true of extensions.
494 if (WebViewRendererState::GetInstance()->IsGuest(process_id
))
497 WebRequestPermissions::HostPermissionsCheck permission_check
=
498 WebRequestPermissions::REQUIRE_ALL_URLS
;
499 switch (host_permissions_strategy()) {
500 case STRATEGY_DEFAULT
: // Default value is already set.
503 permission_check
= WebRequestPermissions::DO_NOT_CHECK_HOST
;
506 permission_check
= WebRequestPermissions::REQUIRE_HOST_PERMISSION
;
509 return WebRequestPermissions::CanExtensionAccessURL(
510 extension_info_map
, extension_id
, request
->url(), crosses_incognito
,
515 scoped_refptr
<const WebRequestAction
> WebRequestAction::Create(
516 content::BrowserContext
* browser_context
,
517 const HostID
& host_id
,
518 const Extension
* extension
,
519 const base::Value
& json_action
,
523 *bad_message
= false;
525 const base::DictionaryValue
* action_dict
= NULL
;
526 INPUT_FORMAT_VALIDATE(json_action
.GetAsDictionary(&action_dict
));
528 std::string instance_type
;
529 INPUT_FORMAT_VALIDATE(
530 action_dict
->GetString(keys::kInstanceTypeKey
, &instance_type
));
532 WebRequestActionFactory
& factory
= g_web_request_action_factory
.Get();
533 return factory
.factory
.Instantiate(
534 instance_type
, action_dict
, error
, bad_message
);
537 void WebRequestAction::Apply(const std::string
& extension_id
,
538 base::Time extension_install_time
,
539 ApplyInfo
* apply_info
) const {
540 if (!HasPermission(apply_info
->extension_info_map
, extension_id
,
541 apply_info
->request_data
.request
,
542 apply_info
->crosses_incognito
))
544 if (stages() & apply_info
->request_data
.stage
) {
545 LinkedPtrEventResponseDelta delta
= CreateDelta(
546 apply_info
->request_data
, extension_id
, extension_install_time
);
548 apply_info
->deltas
->push_back(delta
);
549 if (type() == WebRequestAction::ACTION_IGNORE_RULES
) {
550 const WebRequestIgnoreRulesAction
* ignore_action
=
551 static_cast<const WebRequestIgnoreRulesAction
*>(this);
552 if (!ignore_action
->ignore_tag().empty())
553 apply_info
->ignored_tags
->insert(ignore_action
->ignore_tag());
558 WebRequestAction::WebRequestAction(int stages
,
560 int minimum_priority
,
561 HostPermissionsStrategy strategy
)
564 minimum_priority_(minimum_priority
),
565 host_permissions_strategy_(strategy
) {}
568 // WebRequestCancelAction
571 WebRequestCancelAction::WebRequestCancelAction()
572 : WebRequestAction(ON_BEFORE_REQUEST
| ON_BEFORE_SEND_HEADERS
|
573 ON_HEADERS_RECEIVED
| ON_AUTH_REQUIRED
,
574 ACTION_CANCEL_REQUEST
,
575 std::numeric_limits
<int>::min(),
578 WebRequestCancelAction::~WebRequestCancelAction() {}
580 std::string
WebRequestCancelAction::GetName() const {
581 return keys::kCancelRequestType
;
584 LinkedPtrEventResponseDelta
WebRequestCancelAction::CreateDelta(
585 const WebRequestData
& request_data
,
586 const std::string
& extension_id
,
587 const base::Time
& extension_install_time
) const {
588 CHECK(request_data
.stage
& stages());
589 LinkedPtrEventResponseDelta
result(
590 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
591 result
->cancel
= true;
596 // WebRequestRedirectAction
599 WebRequestRedirectAction::WebRequestRedirectAction(const GURL
& redirect_url
)
600 : WebRequestAction(ON_BEFORE_REQUEST
| ON_HEADERS_RECEIVED
,
601 ACTION_REDIRECT_REQUEST
,
602 std::numeric_limits
<int>::min(),
604 redirect_url_(redirect_url
) {}
606 WebRequestRedirectAction::~WebRequestRedirectAction() {}
608 bool WebRequestRedirectAction::Equals(const WebRequestAction
* other
) const {
609 return WebRequestAction::Equals(other
) &&
611 static_cast<const WebRequestRedirectAction
*>(other
)->redirect_url_
;
614 std::string
WebRequestRedirectAction::GetName() const {
615 return keys::kRedirectRequestType
;
618 LinkedPtrEventResponseDelta
WebRequestRedirectAction::CreateDelta(
619 const WebRequestData
& request_data
,
620 const std::string
& extension_id
,
621 const base::Time
& extension_install_time
) const {
622 CHECK(request_data
.stage
& stages());
623 if (request_data
.request
->url() == redirect_url_
)
624 return LinkedPtrEventResponseDelta(NULL
);
625 LinkedPtrEventResponseDelta
result(
626 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
627 result
->new_url
= redirect_url_
;
632 // WebRequestRedirectToTransparentImageAction
635 WebRequestRedirectToTransparentImageAction::
636 WebRequestRedirectToTransparentImageAction()
637 : WebRequestAction(ON_BEFORE_REQUEST
| ON_HEADERS_RECEIVED
,
638 ACTION_REDIRECT_TO_TRANSPARENT_IMAGE
,
639 std::numeric_limits
<int>::min(),
642 WebRequestRedirectToTransparentImageAction::
643 ~WebRequestRedirectToTransparentImageAction() {}
645 std::string
WebRequestRedirectToTransparentImageAction::GetName() const {
646 return keys::kRedirectToTransparentImageType
;
649 LinkedPtrEventResponseDelta
650 WebRequestRedirectToTransparentImageAction::CreateDelta(
651 const WebRequestData
& request_data
,
652 const std::string
& extension_id
,
653 const base::Time
& extension_install_time
) const {
654 CHECK(request_data
.stage
& stages());
655 LinkedPtrEventResponseDelta
result(
656 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
657 result
->new_url
= GURL(kTransparentImageUrl
);
662 // WebRequestRedirectToEmptyDocumentAction
665 WebRequestRedirectToEmptyDocumentAction::
666 WebRequestRedirectToEmptyDocumentAction()
667 : WebRequestAction(ON_BEFORE_REQUEST
| ON_HEADERS_RECEIVED
,
668 ACTION_REDIRECT_TO_EMPTY_DOCUMENT
,
669 std::numeric_limits
<int>::min(),
672 WebRequestRedirectToEmptyDocumentAction::
673 ~WebRequestRedirectToEmptyDocumentAction() {}
675 std::string
WebRequestRedirectToEmptyDocumentAction::GetName() const {
676 return keys::kRedirectToEmptyDocumentType
;
679 LinkedPtrEventResponseDelta
680 WebRequestRedirectToEmptyDocumentAction::CreateDelta(
681 const WebRequestData
& request_data
,
682 const std::string
& extension_id
,
683 const base::Time
& extension_install_time
) const {
684 CHECK(request_data
.stage
& stages());
685 LinkedPtrEventResponseDelta
result(
686 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
687 result
->new_url
= GURL(kEmptyDocumentUrl
);
692 // WebRequestRedirectByRegExAction
695 WebRequestRedirectByRegExAction::WebRequestRedirectByRegExAction(
696 scoped_ptr
<RE2
> from_pattern
,
697 const std::string
& to_pattern
)
698 : WebRequestAction(ON_BEFORE_REQUEST
| ON_HEADERS_RECEIVED
,
699 ACTION_REDIRECT_BY_REGEX_DOCUMENT
,
700 std::numeric_limits
<int>::min(),
702 from_pattern_(from_pattern
.Pass()),
703 to_pattern_(to_pattern
.data(), to_pattern
.size()) {}
705 WebRequestRedirectByRegExAction::~WebRequestRedirectByRegExAction() {}
707 // About the syntax of the two languages:
709 // ICU (Perl) states:
710 // $n The text of capture group n will be substituted for $n. n must be >= 0
711 // and not greater than the number of capture groups. A $ not followed by a
712 // digit has no special meaning, and will appear in the substitution text
714 // \ Treat the following character as a literal, suppressing any special
715 // meaning. Backslash escaping in substitution text is only required for
716 // '$' and '\', but may be used on any other character without bad effects.
718 // RE2, derived from RE2::Rewrite()
719 // \ May only be followed by a digit or another \. If followed by a single
720 // digit, both characters represent the respective capture group. If followed
721 // by another \, it is used as an escape sequence.
724 std::string
WebRequestRedirectByRegExAction::PerlToRe2Style(
725 const std::string
& perl
) {
726 std::string::const_iterator i
= perl
.begin();
728 while (i
!= perl
.end()) {
731 if (i
== perl
.end()) {
734 } else if (isdigit(*i
)) {
741 } else if (*i
== '\\') {
743 if (i
== perl
.end()) {
745 } else if (*i
== '$') {
747 } else if (*i
== '\\') {
760 bool WebRequestRedirectByRegExAction::Equals(
761 const WebRequestAction
* other
) const {
762 if (!WebRequestAction::Equals(other
))
764 const WebRequestRedirectByRegExAction
* casted_other
=
765 static_cast<const WebRequestRedirectByRegExAction
*>(other
);
766 return from_pattern_
->pattern() == casted_other
->from_pattern_
->pattern() &&
767 to_pattern_
== casted_other
->to_pattern_
;
770 std::string
WebRequestRedirectByRegExAction::GetName() const {
771 return keys::kRedirectByRegExType
;
774 LinkedPtrEventResponseDelta
WebRequestRedirectByRegExAction::CreateDelta(
775 const WebRequestData
& request_data
,
776 const std::string
& extension_id
,
777 const base::Time
& extension_install_time
) const {
778 CHECK(request_data
.stage
& stages());
779 CHECK(from_pattern_
.get());
781 const std::string
& old_url
= request_data
.request
->url().spec();
782 std::string new_url
= old_url
;
783 if (!RE2::Replace(&new_url
, *from_pattern_
, to_pattern_
) ||
784 new_url
== old_url
) {
785 return LinkedPtrEventResponseDelta(NULL
);
788 LinkedPtrEventResponseDelta
result(
789 new extension_web_request_api_helpers::EventResponseDelta(
790 extension_id
, extension_install_time
));
791 result
->new_url
= GURL(new_url
);
796 // WebRequestSetRequestHeaderAction
799 WebRequestSetRequestHeaderAction::WebRequestSetRequestHeaderAction(
800 const std::string
& name
,
801 const std::string
& value
)
802 : WebRequestAction(ON_BEFORE_SEND_HEADERS
,
803 ACTION_SET_REQUEST_HEADER
,
804 std::numeric_limits
<int>::min(),
809 WebRequestSetRequestHeaderAction::~WebRequestSetRequestHeaderAction() {}
811 bool WebRequestSetRequestHeaderAction::Equals(
812 const WebRequestAction
* other
) const {
813 if (!WebRequestAction::Equals(other
))
815 const WebRequestSetRequestHeaderAction
* casted_other
=
816 static_cast<const WebRequestSetRequestHeaderAction
*>(other
);
817 return name_
== casted_other
->name_
&& value_
== casted_other
->value_
;
820 std::string
WebRequestSetRequestHeaderAction::GetName() const {
821 return keys::kSetRequestHeaderType
;
825 LinkedPtrEventResponseDelta
826 WebRequestSetRequestHeaderAction::CreateDelta(
827 const WebRequestData
& request_data
,
828 const std::string
& extension_id
,
829 const base::Time
& extension_install_time
) const {
830 CHECK(request_data
.stage
& stages());
831 LinkedPtrEventResponseDelta
result(
832 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
833 result
->modified_request_headers
.SetHeader(name_
, value_
);
838 // WebRequestRemoveRequestHeaderAction
841 WebRequestRemoveRequestHeaderAction::WebRequestRemoveRequestHeaderAction(
842 const std::string
& name
)
843 : WebRequestAction(ON_BEFORE_SEND_HEADERS
,
844 ACTION_REMOVE_REQUEST_HEADER
,
845 std::numeric_limits
<int>::min(),
849 WebRequestRemoveRequestHeaderAction::~WebRequestRemoveRequestHeaderAction() {}
851 bool WebRequestRemoveRequestHeaderAction::Equals(
852 const WebRequestAction
* other
) const {
853 if (!WebRequestAction::Equals(other
))
855 const WebRequestRemoveRequestHeaderAction
* casted_other
=
856 static_cast<const WebRequestRemoveRequestHeaderAction
*>(other
);
857 return name_
== casted_other
->name_
;
860 std::string
WebRequestRemoveRequestHeaderAction::GetName() const {
861 return keys::kRemoveRequestHeaderType
;
864 LinkedPtrEventResponseDelta
865 WebRequestRemoveRequestHeaderAction::CreateDelta(
866 const WebRequestData
& request_data
,
867 const std::string
& extension_id
,
868 const base::Time
& extension_install_time
) const {
869 CHECK(request_data
.stage
& stages());
870 LinkedPtrEventResponseDelta
result(
871 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
872 result
->deleted_request_headers
.push_back(name_
);
877 // WebRequestAddResponseHeaderAction
880 WebRequestAddResponseHeaderAction::WebRequestAddResponseHeaderAction(
881 const std::string
& name
,
882 const std::string
& value
)
883 : WebRequestAction(ON_HEADERS_RECEIVED
,
884 ACTION_ADD_RESPONSE_HEADER
,
885 std::numeric_limits
<int>::min(),
890 WebRequestAddResponseHeaderAction::~WebRequestAddResponseHeaderAction() {}
892 bool WebRequestAddResponseHeaderAction::Equals(
893 const WebRequestAction
* other
) const {
894 if (!WebRequestAction::Equals(other
))
896 const WebRequestAddResponseHeaderAction
* casted_other
=
897 static_cast<const WebRequestAddResponseHeaderAction
*>(other
);
898 return name_
== casted_other
->name_
&& value_
== casted_other
->value_
;
901 std::string
WebRequestAddResponseHeaderAction::GetName() const {
902 return keys::kAddResponseHeaderType
;
905 LinkedPtrEventResponseDelta
906 WebRequestAddResponseHeaderAction::CreateDelta(
907 const WebRequestData
& request_data
,
908 const std::string
& extension_id
,
909 const base::Time
& extension_install_time
) const {
910 CHECK(request_data
.stage
& stages());
911 const net::HttpResponseHeaders
* headers
=
912 request_data
.original_response_headers
;
914 return LinkedPtrEventResponseDelta(NULL
);
916 // Don't generate the header if it exists already.
917 if (headers
->HasHeaderValue(name_
, value_
))
918 return LinkedPtrEventResponseDelta(NULL
);
920 LinkedPtrEventResponseDelta
result(
921 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
922 result
->added_response_headers
.push_back(make_pair(name_
, value_
));
927 // WebRequestRemoveResponseHeaderAction
930 WebRequestRemoveResponseHeaderAction::WebRequestRemoveResponseHeaderAction(
931 const std::string
& name
,
932 const std::string
& value
,
934 : WebRequestAction(ON_HEADERS_RECEIVED
,
935 ACTION_REMOVE_RESPONSE_HEADER
,
936 std::numeric_limits
<int>::min(),
940 has_value_(has_value
) {}
942 WebRequestRemoveResponseHeaderAction::~WebRequestRemoveResponseHeaderAction() {}
944 bool WebRequestRemoveResponseHeaderAction::Equals(
945 const WebRequestAction
* other
) const {
946 if (!WebRequestAction::Equals(other
))
948 const WebRequestRemoveResponseHeaderAction
* casted_other
=
949 static_cast<const WebRequestRemoveResponseHeaderAction
*>(other
);
950 return name_
== casted_other
->name_
&& value_
== casted_other
->value_
&&
951 has_value_
== casted_other
->has_value_
;
954 std::string
WebRequestRemoveResponseHeaderAction::GetName() const {
955 return keys::kRemoveResponseHeaderType
;
958 LinkedPtrEventResponseDelta
959 WebRequestRemoveResponseHeaderAction::CreateDelta(
960 const WebRequestData
& request_data
,
961 const std::string
& extension_id
,
962 const base::Time
& extension_install_time
) const {
963 CHECK(request_data
.stage
& stages());
964 const net::HttpResponseHeaders
* headers
=
965 request_data
.original_response_headers
;
967 return LinkedPtrEventResponseDelta(NULL
);
969 LinkedPtrEventResponseDelta
result(
970 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
972 std::string current_value
;
973 while (headers
->EnumerateHeader(&iter
, name_
, ¤t_value
)) {
975 (current_value
.size() != value_
.size() ||
976 !std::equal(current_value
.begin(), current_value
.end(),
978 base::CaseInsensitiveCompare
<char>()))) {
981 result
->deleted_response_headers
.push_back(make_pair(name_
, current_value
));
987 // WebRequestIgnoreRulesAction
990 WebRequestIgnoreRulesAction::WebRequestIgnoreRulesAction(
991 int minimum_priority
,
992 const std::string
& ignore_tag
)
993 : WebRequestAction(ON_BEFORE_REQUEST
| ON_BEFORE_SEND_HEADERS
|
994 ON_HEADERS_RECEIVED
| ON_AUTH_REQUIRED
,
998 ignore_tag_(ignore_tag
) {}
1000 WebRequestIgnoreRulesAction::~WebRequestIgnoreRulesAction() {}
1002 bool WebRequestIgnoreRulesAction::Equals(const WebRequestAction
* other
) const {
1003 if (!WebRequestAction::Equals(other
))
1005 const WebRequestIgnoreRulesAction
* casted_other
=
1006 static_cast<const WebRequestIgnoreRulesAction
*>(other
);
1007 return minimum_priority() == casted_other
->minimum_priority() &&
1008 ignore_tag_
== casted_other
->ignore_tag_
;
1011 std::string
WebRequestIgnoreRulesAction::GetName() const {
1012 return keys::kIgnoreRulesType
;
1015 LinkedPtrEventResponseDelta
WebRequestIgnoreRulesAction::CreateDelta(
1016 const WebRequestData
& request_data
,
1017 const std::string
& extension_id
,
1018 const base::Time
& extension_install_time
) const {
1019 CHECK(request_data
.stage
& stages());
1020 return LinkedPtrEventResponseDelta(NULL
);
1024 // WebRequestRequestCookieAction
1027 WebRequestRequestCookieAction::WebRequestRequestCookieAction(
1028 linked_ptr
<RequestCookieModification
> request_cookie_modification
)
1029 : WebRequestAction(ON_BEFORE_SEND_HEADERS
,
1030 ACTION_MODIFY_REQUEST_COOKIE
,
1031 std::numeric_limits
<int>::min(),
1033 request_cookie_modification_(request_cookie_modification
) {
1034 CHECK(request_cookie_modification_
.get());
1037 WebRequestRequestCookieAction::~WebRequestRequestCookieAction() {}
1039 bool WebRequestRequestCookieAction::Equals(
1040 const WebRequestAction
* other
) const {
1041 if (!WebRequestAction::Equals(other
))
1043 const WebRequestRequestCookieAction
* casted_other
=
1044 static_cast<const WebRequestRequestCookieAction
*>(other
);
1045 return helpers::NullableEquals(
1046 request_cookie_modification_
.get(),
1047 casted_other
->request_cookie_modification_
.get());
1050 std::string
WebRequestRequestCookieAction::GetName() const {
1051 switch (request_cookie_modification_
->type
) {
1053 return keys::kAddRequestCookieType
;
1055 return keys::kEditRequestCookieType
;
1056 case helpers::REMOVE
:
1057 return keys::kRemoveRequestCookieType
;
1063 LinkedPtrEventResponseDelta
WebRequestRequestCookieAction::CreateDelta(
1064 const WebRequestData
& request_data
,
1065 const std::string
& extension_id
,
1066 const base::Time
& extension_install_time
) const {
1067 CHECK(request_data
.stage
& stages());
1068 LinkedPtrEventResponseDelta
result(
1069 new extension_web_request_api_helpers::EventResponseDelta(
1070 extension_id
, extension_install_time
));
1071 result
->request_cookie_modifications
.push_back(
1072 request_cookie_modification_
);
1077 // WebRequestResponseCookieAction
1080 WebRequestResponseCookieAction::WebRequestResponseCookieAction(
1081 linked_ptr
<ResponseCookieModification
> response_cookie_modification
)
1082 : WebRequestAction(ON_HEADERS_RECEIVED
,
1083 ACTION_MODIFY_RESPONSE_COOKIE
,
1084 std::numeric_limits
<int>::min(),
1086 response_cookie_modification_(response_cookie_modification
) {
1087 CHECK(response_cookie_modification_
.get());
1090 WebRequestResponseCookieAction::~WebRequestResponseCookieAction() {}
1092 bool WebRequestResponseCookieAction::Equals(
1093 const WebRequestAction
* other
) const {
1094 if (!WebRequestAction::Equals(other
))
1096 const WebRequestResponseCookieAction
* casted_other
=
1097 static_cast<const WebRequestResponseCookieAction
*>(other
);
1098 return helpers::NullableEquals(
1099 response_cookie_modification_
.get(),
1100 casted_other
->response_cookie_modification_
.get());
1103 std::string
WebRequestResponseCookieAction::GetName() const {
1104 switch (response_cookie_modification_
->type
) {
1106 return keys::kAddResponseCookieType
;
1108 return keys::kEditResponseCookieType
;
1109 case helpers::REMOVE
:
1110 return keys::kRemoveResponseCookieType
;
1116 LinkedPtrEventResponseDelta
WebRequestResponseCookieAction::CreateDelta(
1117 const WebRequestData
& request_data
,
1118 const std::string
& extension_id
,
1119 const base::Time
& extension_install_time
) const {
1120 CHECK(request_data
.stage
& stages());
1121 LinkedPtrEventResponseDelta
result(
1122 new extension_web_request_api_helpers::EventResponseDelta(
1123 extension_id
, extension_install_time
));
1124 result
->response_cookie_modifications
.push_back(
1125 response_cookie_modification_
);
1130 // WebRequestSendMessageToExtensionAction
1133 WebRequestSendMessageToExtensionAction::WebRequestSendMessageToExtensionAction(
1134 const std::string
& message
)
1135 : WebRequestAction(ON_BEFORE_REQUEST
| ON_BEFORE_SEND_HEADERS
|
1136 ON_HEADERS_RECEIVED
| ON_AUTH_REQUIRED
,
1137 ACTION_SEND_MESSAGE_TO_EXTENSION
,
1138 std::numeric_limits
<int>::min(),
1140 message_(message
) {}
1142 WebRequestSendMessageToExtensionAction::
1143 ~WebRequestSendMessageToExtensionAction() {}
1145 bool WebRequestSendMessageToExtensionAction::Equals(
1146 const WebRequestAction
* other
) const {
1147 if (!WebRequestAction::Equals(other
))
1149 const WebRequestSendMessageToExtensionAction
* casted_other
=
1150 static_cast<const WebRequestSendMessageToExtensionAction
*>(other
);
1151 return message_
== casted_other
->message_
;
1154 std::string
WebRequestSendMessageToExtensionAction::GetName() const {
1155 return keys::kSendMessageToExtensionType
;
1158 LinkedPtrEventResponseDelta
WebRequestSendMessageToExtensionAction::CreateDelta(
1159 const WebRequestData
& request_data
,
1160 const std::string
& extension_id
,
1161 const base::Time
& extension_install_time
) const {
1162 CHECK(request_data
.stage
& stages());
1163 LinkedPtrEventResponseDelta
result(
1164 new extension_web_request_api_helpers::EventResponseDelta(
1165 extension_id
, extension_install_time
));
1166 result
->messages_to_extension
.insert(message_
);
1170 } // namespace extensions