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 "chrome/browser/extensions/extension_info_map.h" 21#include "chrome/common/extensions/extension.h" 22#include "content/public/common/url_constants.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 27namespace extensions { 28 29namespace helpers = extension_web_request_api_helpers; 30namespace keys = declarative_webrequest_constants; 31 32namespace { 33// Error messages. 34const char kIgnoreRulesRequiresParameterError[] = 35 "IgnoreRules requires at least one parameter."; 36 37const char kTransparentImageUrl[] = "data:image/png;base64,iVBORw0KGgoAAAANSUh" 38 "EUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg=="; 39const 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 48scoped_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 59void 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 82scoped_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 89scoped_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. 108template <class T> 109scoped_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 117scoped_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 132scoped_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 158scoped_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 173scoped_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 186scoped_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 201scoped_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 216scoped_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 243scoped_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 289scoped_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 335scoped_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 348struct WebRequestActionFactory { 349 DedupingFactory<WebRequestAction> factory; 350 351 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 424base::LazyInstance<WebRequestActionFactory>::Leaky 425 g_web_request_action_factory = LAZY_INSTANCE_INITIALIZER; 426 427} // namespace 428 429// 430// WebRequestAction 431// 432 433WebRequestAction::~WebRequestAction() {} 434 435bool WebRequestAction::Equals(const WebRequestAction* other) const { 436 return type() == other->type(); 437} 438 439bool WebRequestAction::HasPermission(const ExtensionInfoMap* 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 469scoped_refptr<const WebRequestAction> WebRequestAction::Create( 470 const base::Value& json_action, 471 std::string* error, 472 bool* bad_message) { 473 *error = ""; 474 *bad_message = false; 475 476 const base::DictionaryValue* action_dict = NULL; 477 INPUT_FORMAT_VALIDATE(json_action.GetAsDictionary(&action_dict)); 478 479 std::string instance_type; 480 INPUT_FORMAT_VALIDATE( 481 action_dict->GetString(keys::kInstanceTypeKey, &instance_type)); 482 483 WebRequestActionFactory& factory = g_web_request_action_factory.Get(); 484 return factory.factory.Instantiate( 485 instance_type, action_dict, error, bad_message); 486} 487 488void WebRequestAction::Apply(const std::string& extension_id, 489 base::Time extension_install_time, 490 ApplyInfo* apply_info) const { 491 if (!HasPermission(apply_info->extension_info_map, extension_id, 492 apply_info->request_data.request, 493 apply_info->crosses_incognito)) 494 return; 495 if (stages() & apply_info->request_data.stage) { 496 LinkedPtrEventResponseDelta delta = CreateDelta( 497 apply_info->request_data, extension_id, extension_install_time); 498 if (delta.get()) 499 apply_info->deltas->push_back(delta); 500 if (type() == WebRequestAction::ACTION_IGNORE_RULES) { 501 const WebRequestIgnoreRulesAction* ignore_action = 502 static_cast<const WebRequestIgnoreRulesAction*>(this); 503 if (!ignore_action->ignore_tag().empty()) 504 apply_info->ignored_tags->insert(ignore_action->ignore_tag()); 505 } 506 } 507} 508 509WebRequestAction::WebRequestAction(int stages, 510 Type type, 511 int minimum_priority, 512 HostPermissionsStrategy strategy) 513 : stages_(stages), 514 type_(type), 515 minimum_priority_(minimum_priority), 516 host_permissions_strategy_(strategy) {} 517 518// 519// WebRequestCancelAction 520// 521 522WebRequestCancelAction::WebRequestCancelAction() 523 : WebRequestAction(ON_BEFORE_REQUEST | ON_BEFORE_SEND_HEADERS | 524 ON_HEADERS_RECEIVED | ON_AUTH_REQUIRED, 525 ACTION_CANCEL_REQUEST, 526 std::numeric_limits<int>::min(), 527 STRATEGY_NONE) {} 528 529WebRequestCancelAction::~WebRequestCancelAction() {} 530 531std::string WebRequestCancelAction::GetName() const { 532 return keys::kCancelRequestType; 533} 534 535LinkedPtrEventResponseDelta WebRequestCancelAction::CreateDelta( 536 const WebRequestData& request_data, 537 const std::string& extension_id, 538 const base::Time& extension_install_time) const { 539 CHECK(request_data.stage & stages()); 540 LinkedPtrEventResponseDelta result( 541 new helpers::EventResponseDelta(extension_id, extension_install_time)); 542 result->cancel = true; 543 return result; 544} 545 546// 547// WebRequestRedirectAction 548// 549 550WebRequestRedirectAction::WebRequestRedirectAction(const GURL& redirect_url) 551 : WebRequestAction(ON_BEFORE_REQUEST, 552 ACTION_REDIRECT_REQUEST, 553 std::numeric_limits<int>::min(), 554 STRATEGY_DEFAULT), 555 redirect_url_(redirect_url) {} 556 557WebRequestRedirectAction::~WebRequestRedirectAction() {} 558 559bool WebRequestRedirectAction::Equals(const WebRequestAction* other) const { 560 return WebRequestAction::Equals(other) && 561 redirect_url_ == 562 static_cast<const WebRequestRedirectAction*>(other)->redirect_url_; 563} 564 565std::string WebRequestRedirectAction::GetName() const { 566 return keys::kRedirectRequestType; 567} 568 569LinkedPtrEventResponseDelta WebRequestRedirectAction::CreateDelta( 570 const WebRequestData& request_data, 571 const std::string& extension_id, 572 const base::Time& extension_install_time) const { 573 CHECK(request_data.stage & stages()); 574 if (request_data.request->url() == redirect_url_) 575 return LinkedPtrEventResponseDelta(NULL); 576 LinkedPtrEventResponseDelta result( 577 new helpers::EventResponseDelta(extension_id, extension_install_time)); 578 result->new_url = redirect_url_; 579 return result; 580} 581 582// 583// WebRequestRedirectToTransparentImageAction 584// 585 586WebRequestRedirectToTransparentImageAction:: 587 WebRequestRedirectToTransparentImageAction() 588 : WebRequestAction(ON_BEFORE_REQUEST, 589 ACTION_REDIRECT_TO_TRANSPARENT_IMAGE, 590 std::numeric_limits<int>::min(), 591 STRATEGY_NONE) {} 592 593WebRequestRedirectToTransparentImageAction:: 594~WebRequestRedirectToTransparentImageAction() {} 595 596std::string WebRequestRedirectToTransparentImageAction::GetName() const { 597 return keys::kRedirectToTransparentImageType; 598} 599 600LinkedPtrEventResponseDelta 601WebRequestRedirectToTransparentImageAction::CreateDelta( 602 const WebRequestData& request_data, 603 const std::string& extension_id, 604 const base::Time& extension_install_time) const { 605 CHECK(request_data.stage & stages()); 606 LinkedPtrEventResponseDelta result( 607 new helpers::EventResponseDelta(extension_id, extension_install_time)); 608 result->new_url = GURL(kTransparentImageUrl); 609 return result; 610} 611 612// 613// WebRequestRedirectToEmptyDocumentAction 614// 615 616WebRequestRedirectToEmptyDocumentAction:: 617 WebRequestRedirectToEmptyDocumentAction() 618 : WebRequestAction(ON_BEFORE_REQUEST, 619 ACTION_REDIRECT_TO_EMPTY_DOCUMENT, 620 std::numeric_limits<int>::min(), 621 STRATEGY_NONE) {} 622 623WebRequestRedirectToEmptyDocumentAction:: 624~WebRequestRedirectToEmptyDocumentAction() {} 625 626std::string WebRequestRedirectToEmptyDocumentAction::GetName() const { 627 return keys::kRedirectToEmptyDocumentType; 628} 629 630LinkedPtrEventResponseDelta 631WebRequestRedirectToEmptyDocumentAction::CreateDelta( 632 const WebRequestData& request_data, 633 const std::string& extension_id, 634 const base::Time& extension_install_time) const { 635 CHECK(request_data.stage & stages()); 636 LinkedPtrEventResponseDelta result( 637 new helpers::EventResponseDelta(extension_id, extension_install_time)); 638 result->new_url = GURL(kEmptyDocumentUrl); 639 return result; 640} 641 642// 643// WebRequestRedirectByRegExAction 644// 645 646WebRequestRedirectByRegExAction::WebRequestRedirectByRegExAction( 647 scoped_ptr<RE2> from_pattern, 648 const std::string& to_pattern) 649 : WebRequestAction(ON_BEFORE_REQUEST, 650 ACTION_REDIRECT_BY_REGEX_DOCUMENT, 651 std::numeric_limits<int>::min(), 652 STRATEGY_DEFAULT), 653 from_pattern_(from_pattern.Pass()), 654 to_pattern_(to_pattern.data(), to_pattern.size()) {} 655 656WebRequestRedirectByRegExAction::~WebRequestRedirectByRegExAction() {} 657 658// About the syntax of the two languages: 659// 660// ICU (Perl) states: 661// $n The text of capture group n will be substituted for $n. n must be >= 0 662// and not greater than the number of capture groups. A $ not followed by a 663// digit has no special meaning, and will appear in the substitution text 664// as itself, a $. 665// \ Treat the following character as a literal, suppressing any special 666// meaning. Backslash escaping in substitution text is only required for 667// '$' and '\', but may be used on any other character without bad effects. 668// 669// RE2, derived from RE2::Rewrite() 670// \ May only be followed by a digit or another \. If followed by a single 671// digit, both characters represent the respective capture group. If followed 672// by another \, it is used as an escape sequence. 673 674// static 675std::string WebRequestRedirectByRegExAction::PerlToRe2Style( 676 const std::string& perl) { 677 std::string::const_iterator i = perl.begin(); 678 std::string result; 679 while (i != perl.end()) { 680 if (*i == '$') { 681 ++i; 682 if (i == perl.end()) { 683 result += '$'; 684 return result; 685 } else if (isdigit(*i)) { 686 result += '\\'; 687 result += *i; 688 } else { 689 result += '$'; 690 result += *i; 691 } 692 } else if (*i == '\\') { 693 ++i; 694 if (i == perl.end()) { 695 result += '\\'; 696 } else if (*i == '$') { 697 result += '$'; 698 } else if (*i == '\\') { 699 result += "\\\\"; 700 } else { 701 result += *i; 702 } 703 } else { 704 result += *i; 705 } 706 ++i; 707 } 708 return result; 709} 710 711bool WebRequestRedirectByRegExAction::Equals( 712 const WebRequestAction* other) const { 713 if (!WebRequestAction::Equals(other)) 714 return false; 715 const WebRequestRedirectByRegExAction* casted_other = 716 static_cast<const WebRequestRedirectByRegExAction*>(other); 717 return from_pattern_->pattern() == casted_other->from_pattern_->pattern() && 718 to_pattern_ == casted_other->to_pattern_; 719} 720 721std::string WebRequestRedirectByRegExAction::GetName() const { 722 return keys::kRedirectByRegExType; 723} 724 725LinkedPtrEventResponseDelta WebRequestRedirectByRegExAction::CreateDelta( 726 const WebRequestData& request_data, 727 const std::string& extension_id, 728 const base::Time& extension_install_time) const { 729 CHECK(request_data.stage & stages()); 730 CHECK(from_pattern_.get()); 731 732 const std::string& old_url = request_data.request->url().spec(); 733 std::string new_url = old_url; 734 if (!RE2::Replace(&new_url, *from_pattern_, to_pattern_) || 735 new_url == old_url) { 736 return LinkedPtrEventResponseDelta(NULL); 737 } 738 739 LinkedPtrEventResponseDelta result( 740 new extension_web_request_api_helpers::EventResponseDelta( 741 extension_id, extension_install_time)); 742 result->new_url = GURL(new_url); 743 return result; 744} 745 746// 747// WebRequestSetRequestHeaderAction 748// 749 750WebRequestSetRequestHeaderAction::WebRequestSetRequestHeaderAction( 751 const std::string& name, 752 const std::string& value) 753 : WebRequestAction(ON_BEFORE_SEND_HEADERS, 754 ACTION_SET_REQUEST_HEADER, 755 std::numeric_limits<int>::min(), 756 STRATEGY_DEFAULT), 757 name_(name), 758 value_(value) {} 759 760WebRequestSetRequestHeaderAction::~WebRequestSetRequestHeaderAction() {} 761 762bool WebRequestSetRequestHeaderAction::Equals( 763 const WebRequestAction* other) const { 764 if (!WebRequestAction::Equals(other)) 765 return false; 766 const WebRequestSetRequestHeaderAction* casted_other = 767 static_cast<const WebRequestSetRequestHeaderAction*>(other); 768 return name_ == casted_other->name_ && value_ == casted_other->value_; 769} 770 771std::string WebRequestSetRequestHeaderAction::GetName() const { 772 return keys::kSetRequestHeaderType; 773} 774 775 776LinkedPtrEventResponseDelta 777WebRequestSetRequestHeaderAction::CreateDelta( 778 const WebRequestData& request_data, 779 const std::string& extension_id, 780 const base::Time& extension_install_time) const { 781 CHECK(request_data.stage & stages()); 782 LinkedPtrEventResponseDelta result( 783 new helpers::EventResponseDelta(extension_id, extension_install_time)); 784 result->modified_request_headers.SetHeader(name_, value_); 785 return result; 786} 787 788// 789// WebRequestRemoveRequestHeaderAction 790// 791 792WebRequestRemoveRequestHeaderAction::WebRequestRemoveRequestHeaderAction( 793 const std::string& name) 794 : WebRequestAction(ON_BEFORE_SEND_HEADERS, 795 ACTION_REMOVE_REQUEST_HEADER, 796 std::numeric_limits<int>::min(), 797 STRATEGY_DEFAULT), 798 name_(name) {} 799 800WebRequestRemoveRequestHeaderAction::~WebRequestRemoveRequestHeaderAction() {} 801 802bool WebRequestRemoveRequestHeaderAction::Equals( 803 const WebRequestAction* other) const { 804 if (!WebRequestAction::Equals(other)) 805 return false; 806 const WebRequestRemoveRequestHeaderAction* casted_other = 807 static_cast<const WebRequestRemoveRequestHeaderAction*>(other); 808 return name_ == casted_other->name_; 809} 810 811std::string WebRequestRemoveRequestHeaderAction::GetName() const { 812 return keys::kRemoveRequestHeaderType; 813} 814 815LinkedPtrEventResponseDelta 816WebRequestRemoveRequestHeaderAction::CreateDelta( 817 const WebRequestData& request_data, 818 const std::string& extension_id, 819 const base::Time& extension_install_time) const { 820 CHECK(request_data.stage & stages()); 821 LinkedPtrEventResponseDelta result( 822 new helpers::EventResponseDelta(extension_id, extension_install_time)); 823 result->deleted_request_headers.push_back(name_); 824 return result; 825} 826 827// 828// WebRequestAddResponseHeaderAction 829// 830 831WebRequestAddResponseHeaderAction::WebRequestAddResponseHeaderAction( 832 const std::string& name, 833 const std::string& value) 834 : WebRequestAction(ON_HEADERS_RECEIVED, 835 ACTION_ADD_RESPONSE_HEADER, 836 std::numeric_limits<int>::min(), 837 STRATEGY_DEFAULT), 838 name_(name), 839 value_(value) {} 840 841WebRequestAddResponseHeaderAction::~WebRequestAddResponseHeaderAction() {} 842 843bool WebRequestAddResponseHeaderAction::Equals( 844 const WebRequestAction* other) const { 845 if (!WebRequestAction::Equals(other)) 846 return false; 847 const WebRequestAddResponseHeaderAction* casted_other = 848 static_cast<const WebRequestAddResponseHeaderAction*>(other); 849 return name_ == casted_other->name_ && value_ == casted_other->value_; 850} 851 852std::string WebRequestAddResponseHeaderAction::GetName() const { 853 return keys::kAddResponseHeaderType; 854} 855 856LinkedPtrEventResponseDelta 857WebRequestAddResponseHeaderAction::CreateDelta( 858 const WebRequestData& request_data, 859 const std::string& extension_id, 860 const base::Time& extension_install_time) const { 861 CHECK(request_data.stage & stages()); 862 const net::HttpResponseHeaders* headers = 863 request_data.original_response_headers; 864 if (!headers) 865 return LinkedPtrEventResponseDelta(NULL); 866 867 // Don't generate the header if it exists already. 868 if (headers->HasHeaderValue(name_, value_)) 869 return LinkedPtrEventResponseDelta(NULL); 870 871 LinkedPtrEventResponseDelta result( 872 new helpers::EventResponseDelta(extension_id, extension_install_time)); 873 result->added_response_headers.push_back(make_pair(name_, value_)); 874 return result; 875} 876 877// 878// WebRequestRemoveResponseHeaderAction 879// 880 881WebRequestRemoveResponseHeaderAction::WebRequestRemoveResponseHeaderAction( 882 const std::string& name, 883 const std::string& value, 884 bool has_value) 885 : WebRequestAction(ON_HEADERS_RECEIVED, 886 ACTION_REMOVE_RESPONSE_HEADER, 887 std::numeric_limits<int>::min(), 888 STRATEGY_DEFAULT), 889 name_(name), 890 value_(value), 891 has_value_(has_value) {} 892 893WebRequestRemoveResponseHeaderAction::~WebRequestRemoveResponseHeaderAction() {} 894 895bool WebRequestRemoveResponseHeaderAction::Equals( 896 const WebRequestAction* other) const { 897 if (!WebRequestAction::Equals(other)) 898 return false; 899 const WebRequestRemoveResponseHeaderAction* casted_other = 900 static_cast<const WebRequestRemoveResponseHeaderAction*>(other); 901 return name_ == casted_other->name_ && value_ == casted_other->value_ && 902 has_value_ == casted_other->has_value_; 903} 904 905std::string WebRequestRemoveResponseHeaderAction::GetName() const { 906 return keys::kRemoveResponseHeaderType; 907} 908 909LinkedPtrEventResponseDelta 910WebRequestRemoveResponseHeaderAction::CreateDelta( 911 const WebRequestData& request_data, 912 const std::string& extension_id, 913 const base::Time& extension_install_time) const { 914 CHECK(request_data.stage & stages()); 915 const net::HttpResponseHeaders* headers = 916 request_data.original_response_headers; 917 if (!headers) 918 return LinkedPtrEventResponseDelta(NULL); 919 920 LinkedPtrEventResponseDelta result( 921 new helpers::EventResponseDelta(extension_id, extension_install_time)); 922 void* iter = NULL; 923 std::string current_value; 924 while (headers->EnumerateHeader(&iter, name_, ¤t_value)) { 925 if (has_value_ && 926 (current_value.size() != value_.size() || 927 !std::equal(current_value.begin(), current_value.end(), 928 value_.begin(), 929 base::CaseInsensitiveCompare<char>()))) { 930 continue; 931 } 932 result->deleted_response_headers.push_back(make_pair(name_, current_value)); 933 } 934 return result; 935} 936 937// 938// WebRequestIgnoreRulesAction 939// 940 941WebRequestIgnoreRulesAction::WebRequestIgnoreRulesAction( 942 int minimum_priority, 943 const std::string& ignore_tag) 944 : WebRequestAction(ON_BEFORE_REQUEST | ON_BEFORE_SEND_HEADERS | 945 ON_HEADERS_RECEIVED | ON_AUTH_REQUIRED, 946 ACTION_IGNORE_RULES, 947 minimum_priority, 948 STRATEGY_NONE), 949 ignore_tag_(ignore_tag) {} 950 951WebRequestIgnoreRulesAction::~WebRequestIgnoreRulesAction() {} 952 953bool WebRequestIgnoreRulesAction::Equals(const WebRequestAction* other) const { 954 if (!WebRequestAction::Equals(other)) 955 return false; 956 const WebRequestIgnoreRulesAction* casted_other = 957 static_cast<const WebRequestIgnoreRulesAction*>(other); 958 return minimum_priority() == casted_other->minimum_priority() && 959 ignore_tag_ == casted_other->ignore_tag_; 960} 961 962std::string WebRequestIgnoreRulesAction::GetName() const { 963 return keys::kIgnoreRulesType; 964} 965 966LinkedPtrEventResponseDelta WebRequestIgnoreRulesAction::CreateDelta( 967 const WebRequestData& request_data, 968 const std::string& extension_id, 969 const base::Time& extension_install_time) const { 970 CHECK(request_data.stage & stages()); 971 return LinkedPtrEventResponseDelta(NULL); 972} 973 974// 975// WebRequestRequestCookieAction 976// 977 978WebRequestRequestCookieAction::WebRequestRequestCookieAction( 979 linked_ptr<RequestCookieModification> request_cookie_modification) 980 : WebRequestAction(ON_BEFORE_SEND_HEADERS, 981 ACTION_MODIFY_REQUEST_COOKIE, 982 std::numeric_limits<int>::min(), 983 STRATEGY_DEFAULT), 984 request_cookie_modification_(request_cookie_modification) { 985 CHECK(request_cookie_modification_.get()); 986} 987 988WebRequestRequestCookieAction::~WebRequestRequestCookieAction() {} 989 990bool WebRequestRequestCookieAction::Equals( 991 const WebRequestAction* other) const { 992 if (!WebRequestAction::Equals(other)) 993 return false; 994 const WebRequestRequestCookieAction* casted_other = 995 static_cast<const WebRequestRequestCookieAction*>(other); 996 return helpers::NullableEquals( 997 request_cookie_modification_.get(), 998 casted_other->request_cookie_modification_.get()); 999} 1000 1001std::string WebRequestRequestCookieAction::GetName() const { 1002 switch (request_cookie_modification_->type) { 1003 case helpers::ADD: 1004 return keys::kAddRequestCookieType; 1005 case helpers::EDIT: 1006 return keys::kEditRequestCookieType; 1007 case helpers::REMOVE: 1008 return keys::kRemoveRequestCookieType; 1009 } 1010 NOTREACHED(); 1011 return ""; 1012} 1013 1014LinkedPtrEventResponseDelta WebRequestRequestCookieAction::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 LinkedPtrEventResponseDelta result( 1020 new extension_web_request_api_helpers::EventResponseDelta( 1021 extension_id, extension_install_time)); 1022 result->request_cookie_modifications.push_back( 1023 request_cookie_modification_); 1024 return result; 1025} 1026 1027// 1028// WebRequestResponseCookieAction 1029// 1030 1031WebRequestResponseCookieAction::WebRequestResponseCookieAction( 1032 linked_ptr<ResponseCookieModification> response_cookie_modification) 1033 : WebRequestAction(ON_HEADERS_RECEIVED, 1034 ACTION_MODIFY_RESPONSE_COOKIE, 1035 std::numeric_limits<int>::min(), 1036 STRATEGY_DEFAULT), 1037 response_cookie_modification_(response_cookie_modification) { 1038 CHECK(response_cookie_modification_.get()); 1039} 1040 1041WebRequestResponseCookieAction::~WebRequestResponseCookieAction() {} 1042 1043bool WebRequestResponseCookieAction::Equals( 1044 const WebRequestAction* other) const { 1045 if (!WebRequestAction::Equals(other)) 1046 return false; 1047 const WebRequestResponseCookieAction* casted_other = 1048 static_cast<const WebRequestResponseCookieAction*>(other); 1049 return helpers::NullableEquals( 1050 response_cookie_modification_.get(), 1051 casted_other->response_cookie_modification_.get()); 1052} 1053 1054std::string WebRequestResponseCookieAction::GetName() const { 1055 switch (response_cookie_modification_->type) { 1056 case helpers::ADD: 1057 return keys::kAddResponseCookieType; 1058 case helpers::EDIT: 1059 return keys::kEditResponseCookieType; 1060 case helpers::REMOVE: 1061 return keys::kRemoveResponseCookieType; 1062 } 1063 NOTREACHED(); 1064 return ""; 1065} 1066 1067LinkedPtrEventResponseDelta WebRequestResponseCookieAction::CreateDelta( 1068 const WebRequestData& request_data, 1069 const std::string& extension_id, 1070 const base::Time& extension_install_time) const { 1071 CHECK(request_data.stage & stages()); 1072 LinkedPtrEventResponseDelta result( 1073 new extension_web_request_api_helpers::EventResponseDelta( 1074 extension_id, extension_install_time)); 1075 result->response_cookie_modifications.push_back( 1076 response_cookie_modification_); 1077 return result; 1078} 1079 1080// 1081// WebRequestSendMessageToExtensionAction 1082// 1083 1084WebRequestSendMessageToExtensionAction::WebRequestSendMessageToExtensionAction( 1085 const std::string& message) 1086 : WebRequestAction(ON_BEFORE_REQUEST | ON_BEFORE_SEND_HEADERS | 1087 ON_HEADERS_RECEIVED | ON_AUTH_REQUIRED, 1088 ACTION_SEND_MESSAGE_TO_EXTENSION, 1089 std::numeric_limits<int>::min(), 1090 STRATEGY_HOST), 1091 message_(message) {} 1092 1093WebRequestSendMessageToExtensionAction:: 1094~WebRequestSendMessageToExtensionAction() {} 1095 1096bool WebRequestSendMessageToExtensionAction::Equals( 1097 const WebRequestAction* other) const { 1098 if (!WebRequestAction::Equals(other)) 1099 return false; 1100 const WebRequestSendMessageToExtensionAction* casted_other = 1101 static_cast<const WebRequestSendMessageToExtensionAction*>(other); 1102 return message_ == casted_other->message_; 1103} 1104 1105std::string WebRequestSendMessageToExtensionAction::GetName() const { 1106 return keys::kSendMessageToExtensionType; 1107} 1108 1109LinkedPtrEventResponseDelta WebRequestSendMessageToExtensionAction::CreateDelta( 1110 const WebRequestData& request_data, 1111 const std::string& extension_id, 1112 const base::Time& extension_install_time) const { 1113 CHECK(request_data.stage & stages()); 1114 LinkedPtrEventResponseDelta result( 1115 new extension_web_request_api_helpers::EventResponseDelta( 1116 extension_id, extension_install_time)); 1117 result->messages_to_extension.insert(message_); 1118 return result; 1119} 1120 1121} // namespace extensions 1122