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