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