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