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 Extension
* extension
,
518 const base::Value
& json_action
,
522 *bad_message
= false;
524 const base::DictionaryValue
* action_dict
= NULL
;
525 INPUT_FORMAT_VALIDATE(json_action
.GetAsDictionary(&action_dict
));
527 std::string instance_type
;
528 INPUT_FORMAT_VALIDATE(
529 action_dict
->GetString(keys::kInstanceTypeKey
, &instance_type
));
531 WebRequestActionFactory
& factory
= g_web_request_action_factory
.Get();
532 return factory
.factory
.Instantiate(
533 instance_type
, action_dict
, error
, bad_message
);
536 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
))
543 if (stages() & apply_info
->request_data
.stage
) {
544 LinkedPtrEventResponseDelta delta
= CreateDelta(
545 apply_info
->request_data
, extension_id
, extension_install_time
);
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());
557 WebRequestAction::WebRequestAction(int stages
,
559 int minimum_priority
,
560 HostPermissionsStrategy strategy
)
563 minimum_priority_(minimum_priority
),
564 host_permissions_strategy_(strategy
) {}
567 // 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(),
577 WebRequestCancelAction::~WebRequestCancelAction() {}
579 std::string
WebRequestCancelAction::GetName() const {
580 return keys::kCancelRequestType
;
583 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;
595 // WebRequestRedirectAction
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(),
603 redirect_url_(redirect_url
) {}
605 WebRequestRedirectAction::~WebRequestRedirectAction() {}
607 bool WebRequestRedirectAction::Equals(const WebRequestAction
* other
) const {
608 return WebRequestAction::Equals(other
) &&
610 static_cast<const WebRequestRedirectAction
*>(other
)->redirect_url_
;
613 std::string
WebRequestRedirectAction::GetName() const {
614 return keys::kRedirectRequestType
;
617 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_
;
631 // WebRequestRedirectToTransparentImageAction
634 WebRequestRedirectToTransparentImageAction::
635 WebRequestRedirectToTransparentImageAction()
636 : WebRequestAction(ON_BEFORE_REQUEST
| ON_HEADERS_RECEIVED
,
637 ACTION_REDIRECT_TO_TRANSPARENT_IMAGE
,
638 std::numeric_limits
<int>::min(),
641 WebRequestRedirectToTransparentImageAction::
642 ~WebRequestRedirectToTransparentImageAction() {}
644 std::string
WebRequestRedirectToTransparentImageAction::GetName() const {
645 return keys::kRedirectToTransparentImageType
;
648 LinkedPtrEventResponseDelta
649 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
);
661 // WebRequestRedirectToEmptyDocumentAction
664 WebRequestRedirectToEmptyDocumentAction::
665 WebRequestRedirectToEmptyDocumentAction()
666 : WebRequestAction(ON_BEFORE_REQUEST
| ON_HEADERS_RECEIVED
,
667 ACTION_REDIRECT_TO_EMPTY_DOCUMENT
,
668 std::numeric_limits
<int>::min(),
671 WebRequestRedirectToEmptyDocumentAction::
672 ~WebRequestRedirectToEmptyDocumentAction() {}
674 std::string
WebRequestRedirectToEmptyDocumentAction::GetName() const {
675 return keys::kRedirectToEmptyDocumentType
;
678 LinkedPtrEventResponseDelta
679 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
);
691 // WebRequestRedirectByRegExAction
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(),
701 from_pattern_(from_pattern
.Pass()),
702 to_pattern_(to_pattern
.data(), to_pattern
.size()) {}
704 WebRequestRedirectByRegExAction::~WebRequestRedirectByRegExAction() {}
706 // About the syntax of the two languages:
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
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.
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.
723 std::string
WebRequestRedirectByRegExAction::PerlToRe2Style(
724 const std::string
& perl
) {
725 std::string::const_iterator i
= perl
.begin();
727 while (i
!= perl
.end()) {
730 if (i
== perl
.end()) {
733 } else if (isdigit(*i
)) {
740 } else if (*i
== '\\') {
742 if (i
== perl
.end()) {
744 } else if (*i
== '$') {
746 } else if (*i
== '\\') {
759 bool WebRequestRedirectByRegExAction::Equals(
760 const WebRequestAction
* other
) const {
761 if (!WebRequestAction::Equals(other
))
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_
;
769 std::string
WebRequestRedirectByRegExAction::GetName() const {
770 return keys::kRedirectByRegExType
;
773 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());
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
);
787 LinkedPtrEventResponseDelta
result(
788 new extension_web_request_api_helpers::EventResponseDelta(
789 extension_id
, extension_install_time
));
790 result
->new_url
= GURL(new_url
);
795 // WebRequestSetRequestHeaderAction
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(),
808 WebRequestSetRequestHeaderAction::~WebRequestSetRequestHeaderAction() {}
810 bool WebRequestSetRequestHeaderAction::Equals(
811 const WebRequestAction
* other
) const {
812 if (!WebRequestAction::Equals(other
))
814 const WebRequestSetRequestHeaderAction
* casted_other
=
815 static_cast<const WebRequestSetRequestHeaderAction
*>(other
);
816 return name_
== casted_other
->name_
&& value_
== casted_other
->value_
;
819 std::string
WebRequestSetRequestHeaderAction::GetName() const {
820 return keys::kSetRequestHeaderType
;
824 LinkedPtrEventResponseDelta
825 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_
);
837 // WebRequestRemoveRequestHeaderAction
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(),
848 WebRequestRemoveRequestHeaderAction::~WebRequestRemoveRequestHeaderAction() {}
850 bool WebRequestRemoveRequestHeaderAction::Equals(
851 const WebRequestAction
* other
) const {
852 if (!WebRequestAction::Equals(other
))
854 const WebRequestRemoveRequestHeaderAction
* casted_other
=
855 static_cast<const WebRequestRemoveRequestHeaderAction
*>(other
);
856 return name_
== casted_other
->name_
;
859 std::string
WebRequestRemoveRequestHeaderAction::GetName() const {
860 return keys::kRemoveRequestHeaderType
;
863 LinkedPtrEventResponseDelta
864 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_
);
876 // WebRequestAddResponseHeaderAction
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(),
889 WebRequestAddResponseHeaderAction::~WebRequestAddResponseHeaderAction() {}
891 bool WebRequestAddResponseHeaderAction::Equals(
892 const WebRequestAction
* other
) const {
893 if (!WebRequestAction::Equals(other
))
895 const WebRequestAddResponseHeaderAction
* casted_other
=
896 static_cast<const WebRequestAddResponseHeaderAction
*>(other
);
897 return name_
== casted_other
->name_
&& value_
== casted_other
->value_
;
900 std::string
WebRequestAddResponseHeaderAction::GetName() const {
901 return keys::kAddResponseHeaderType
;
904 LinkedPtrEventResponseDelta
905 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
;
913 return LinkedPtrEventResponseDelta(NULL
);
915 // Don't generate the header if it exists already.
916 if (headers
->HasHeaderValue(name_
, value_
))
917 return LinkedPtrEventResponseDelta(NULL
);
919 LinkedPtrEventResponseDelta
result(
920 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
921 result
->added_response_headers
.push_back(make_pair(name_
, value_
));
926 // WebRequestRemoveResponseHeaderAction
929 WebRequestRemoveResponseHeaderAction::WebRequestRemoveResponseHeaderAction(
930 const std::string
& name
,
931 const std::string
& value
,
933 : WebRequestAction(ON_HEADERS_RECEIVED
,
934 ACTION_REMOVE_RESPONSE_HEADER
,
935 std::numeric_limits
<int>::min(),
939 has_value_(has_value
) {}
941 WebRequestRemoveResponseHeaderAction::~WebRequestRemoveResponseHeaderAction() {}
943 bool WebRequestRemoveResponseHeaderAction::Equals(
944 const WebRequestAction
* other
) const {
945 if (!WebRequestAction::Equals(other
))
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_
;
953 std::string
WebRequestRemoveResponseHeaderAction::GetName() const {
954 return keys::kRemoveResponseHeaderType
;
957 LinkedPtrEventResponseDelta
958 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
;
966 return LinkedPtrEventResponseDelta(NULL
);
968 LinkedPtrEventResponseDelta
result(
969 new helpers::EventResponseDelta(extension_id
, extension_install_time
));
971 std::string current_value
;
972 while (headers
->EnumerateHeader(&iter
, name_
, ¤t_value
)) {
973 if (has_value_
&& !base::EqualsCaseInsensitiveASCII(current_value
, value_
))
975 result
->deleted_response_headers
.push_back(make_pair(name_
, current_value
));
981 // WebRequestIgnoreRulesAction
984 WebRequestIgnoreRulesAction::WebRequestIgnoreRulesAction(
985 int minimum_priority
,
986 const std::string
& ignore_tag
)
987 : WebRequestAction(ON_BEFORE_REQUEST
| ON_BEFORE_SEND_HEADERS
|
988 ON_HEADERS_RECEIVED
| ON_AUTH_REQUIRED
,
992 ignore_tag_(ignore_tag
) {}
994 WebRequestIgnoreRulesAction::~WebRequestIgnoreRulesAction() {}
996 bool WebRequestIgnoreRulesAction::Equals(const WebRequestAction
* other
) const {
997 if (!WebRequestAction::Equals(other
))
999 const WebRequestIgnoreRulesAction
* casted_other
=
1000 static_cast<const WebRequestIgnoreRulesAction
*>(other
);
1001 return minimum_priority() == casted_other
->minimum_priority() &&
1002 ignore_tag_
== casted_other
->ignore_tag_
;
1005 std::string
WebRequestIgnoreRulesAction::GetName() const {
1006 return keys::kIgnoreRulesType
;
1009 LinkedPtrEventResponseDelta
WebRequestIgnoreRulesAction::CreateDelta(
1010 const WebRequestData
& request_data
,
1011 const std::string
& extension_id
,
1012 const base::Time
& extension_install_time
) const {
1013 CHECK(request_data
.stage
& stages());
1014 return LinkedPtrEventResponseDelta(NULL
);
1018 // WebRequestRequestCookieAction
1021 WebRequestRequestCookieAction::WebRequestRequestCookieAction(
1022 linked_ptr
<RequestCookieModification
> request_cookie_modification
)
1023 : WebRequestAction(ON_BEFORE_SEND_HEADERS
,
1024 ACTION_MODIFY_REQUEST_COOKIE
,
1025 std::numeric_limits
<int>::min(),
1027 request_cookie_modification_(request_cookie_modification
) {
1028 CHECK(request_cookie_modification_
.get());
1031 WebRequestRequestCookieAction::~WebRequestRequestCookieAction() {}
1033 bool WebRequestRequestCookieAction::Equals(
1034 const WebRequestAction
* other
) const {
1035 if (!WebRequestAction::Equals(other
))
1037 const WebRequestRequestCookieAction
* casted_other
=
1038 static_cast<const WebRequestRequestCookieAction
*>(other
);
1039 return helpers::NullableEquals(
1040 request_cookie_modification_
.get(),
1041 casted_other
->request_cookie_modification_
.get());
1044 std::string
WebRequestRequestCookieAction::GetName() const {
1045 switch (request_cookie_modification_
->type
) {
1047 return keys::kAddRequestCookieType
;
1049 return keys::kEditRequestCookieType
;
1050 case helpers::REMOVE
:
1051 return keys::kRemoveRequestCookieType
;
1057 LinkedPtrEventResponseDelta
WebRequestRequestCookieAction::CreateDelta(
1058 const WebRequestData
& request_data
,
1059 const std::string
& extension_id
,
1060 const base::Time
& extension_install_time
) const {
1061 CHECK(request_data
.stage
& stages());
1062 LinkedPtrEventResponseDelta
result(
1063 new extension_web_request_api_helpers::EventResponseDelta(
1064 extension_id
, extension_install_time
));
1065 result
->request_cookie_modifications
.push_back(
1066 request_cookie_modification_
);
1071 // WebRequestResponseCookieAction
1074 WebRequestResponseCookieAction::WebRequestResponseCookieAction(
1075 linked_ptr
<ResponseCookieModification
> response_cookie_modification
)
1076 : WebRequestAction(ON_HEADERS_RECEIVED
,
1077 ACTION_MODIFY_RESPONSE_COOKIE
,
1078 std::numeric_limits
<int>::min(),
1080 response_cookie_modification_(response_cookie_modification
) {
1081 CHECK(response_cookie_modification_
.get());
1084 WebRequestResponseCookieAction::~WebRequestResponseCookieAction() {}
1086 bool WebRequestResponseCookieAction::Equals(
1087 const WebRequestAction
* other
) const {
1088 if (!WebRequestAction::Equals(other
))
1090 const WebRequestResponseCookieAction
* casted_other
=
1091 static_cast<const WebRequestResponseCookieAction
*>(other
);
1092 return helpers::NullableEquals(
1093 response_cookie_modification_
.get(),
1094 casted_other
->response_cookie_modification_
.get());
1097 std::string
WebRequestResponseCookieAction::GetName() const {
1098 switch (response_cookie_modification_
->type
) {
1100 return keys::kAddResponseCookieType
;
1102 return keys::kEditResponseCookieType
;
1103 case helpers::REMOVE
:
1104 return keys::kRemoveResponseCookieType
;
1110 LinkedPtrEventResponseDelta
WebRequestResponseCookieAction::CreateDelta(
1111 const WebRequestData
& request_data
,
1112 const std::string
& extension_id
,
1113 const base::Time
& extension_install_time
) const {
1114 CHECK(request_data
.stage
& stages());
1115 LinkedPtrEventResponseDelta
result(
1116 new extension_web_request_api_helpers::EventResponseDelta(
1117 extension_id
, extension_install_time
));
1118 result
->response_cookie_modifications
.push_back(
1119 response_cookie_modification_
);
1124 // WebRequestSendMessageToExtensionAction
1127 WebRequestSendMessageToExtensionAction::WebRequestSendMessageToExtensionAction(
1128 const std::string
& message
)
1129 : WebRequestAction(ON_BEFORE_REQUEST
| ON_BEFORE_SEND_HEADERS
|
1130 ON_HEADERS_RECEIVED
| ON_AUTH_REQUIRED
,
1131 ACTION_SEND_MESSAGE_TO_EXTENSION
,
1132 std::numeric_limits
<int>::min(),
1134 message_(message
) {}
1136 WebRequestSendMessageToExtensionAction::
1137 ~WebRequestSendMessageToExtensionAction() {}
1139 bool WebRequestSendMessageToExtensionAction::Equals(
1140 const WebRequestAction
* other
) const {
1141 if (!WebRequestAction::Equals(other
))
1143 const WebRequestSendMessageToExtensionAction
* casted_other
=
1144 static_cast<const WebRequestSendMessageToExtensionAction
*>(other
);
1145 return message_
== casted_other
->message_
;
1148 std::string
WebRequestSendMessageToExtensionAction::GetName() const {
1149 return keys::kSendMessageToExtensionType
;
1152 LinkedPtrEventResponseDelta
WebRequestSendMessageToExtensionAction::CreateDelta(
1153 const WebRequestData
& request_data
,
1154 const std::string
& extension_id
,
1155 const base::Time
& extension_install_time
) const {
1156 CHECK(request_data
.stage
& stages());
1157 LinkedPtrEventResponseDelta
result(
1158 new extension_web_request_api_helpers::EventResponseDelta(
1159 extension_id
, extension_install_time
));
1160 result
->messages_to_extension
.insert(message_
);
1164 } // namespace extensions