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