OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_action .h" | 5 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_action .h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/stringprintf.h" | 11 #include "base/stringprintf.h" |
12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
13 #include "base/utf_string_conversions.h" | |
13 #include "base/values.h" | 14 #include "base/values.h" |
14 #include "chrome/browser/extensions/api/declarative_webrequest/request_stages.h" | 15 #include "chrome/browser/extensions/api/declarative_webrequest/request_stages.h" |
15 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_consta nts.h" | 16 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_consta nts.h" |
16 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h" | 17 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h" |
17 #include "net/url_request/url_request.h" | 18 #include "net/url_request/url_request.h" |
18 | 19 |
19 namespace extensions { | 20 namespace extensions { |
20 | 21 |
21 namespace keys = declarative_webrequest_constants; | 22 namespace keys = declarative_webrequest_constants; |
22 | 23 |
(...skipping 28 matching lines...) Expand all Loading... | |
51 std::string* error, | 52 std::string* error, |
52 bool* bad_message) { | 53 bool* bad_message) { |
53 std::string redirect_url_string; | 54 std::string redirect_url_string; |
54 INPUT_FORMAT_VALIDATE( | 55 INPUT_FORMAT_VALIDATE( |
55 dict->GetString(keys::kRedirectUrlKey, &redirect_url_string)); | 56 dict->GetString(keys::kRedirectUrlKey, &redirect_url_string)); |
56 GURL redirect_url(redirect_url_string); | 57 GURL redirect_url(redirect_url_string); |
57 return scoped_ptr<WebRequestAction>( | 58 return scoped_ptr<WebRequestAction>( |
58 new WebRequestRedirectAction(redirect_url)); | 59 new WebRequestRedirectAction(redirect_url)); |
59 } | 60 } |
60 | 61 |
62 scoped_ptr<WebRequestAction> CreateRedirectRequestByRegExAction( | |
63 const base::DictionaryValue* dict, | |
64 std::string* error, | |
65 bool* bad_message) { | |
66 std::string from; | |
67 std::string to; | |
68 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kFromKey, &from)); | |
69 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kToKey, &to)); | |
70 | |
71 // TODO(battre): Add this line once we migrate from ICU RegEx to RE2 RegEx.s | |
72 // to = WebRequestRedirectByRegExAction::PerlToRe2Style(to); | |
73 | |
74 UParseError parse_error; | |
75 UErrorCode status = U_ZERO_ERROR; | |
76 scoped_ptr<icu::RegexPattern> pattern( | |
77 icu::RegexPattern::compile(icu::UnicodeString(from.data(), from.size()), | |
78 0, parse_error, status)); | |
79 if (U_FAILURE(status) || !pattern.get()) { | |
80 *error = "Invalid pattern '" + from + "' -> '" + to + "'"; | |
81 return scoped_ptr<WebRequestAction>(NULL); | |
82 } | |
83 return scoped_ptr<WebRequestAction>( | |
84 new WebRequestRedirectByRegExAction(pattern.Pass(), to)); | |
85 } | |
86 | |
61 scoped_ptr<WebRequestAction> CreateSetRequestHeaderAction( | 87 scoped_ptr<WebRequestAction> CreateSetRequestHeaderAction( |
62 const base::DictionaryValue* dict, | 88 const base::DictionaryValue* dict, |
63 std::string* error, | 89 std::string* error, |
64 bool* bad_message) { | 90 bool* bad_message) { |
65 std::string name; | 91 std::string name; |
66 std::string value; | 92 std::string value; |
67 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kNameKey, &name)); | 93 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kNameKey, &name)); |
68 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kValueKey, &value)); | 94 INPUT_FORMAT_VALIDATE(dict->GetString(keys::kValueKey, &value)); |
69 return scoped_ptr<WebRequestAction>( | 95 return scoped_ptr<WebRequestAction>( |
70 new WebRequestSetRequestHeaderAction(name, value)); | 96 new WebRequestSetRequestHeaderAction(name, value)); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
125 (* FactoryMethod)(const base::DictionaryValue* /* dict */ , | 151 (* FactoryMethod)(const base::DictionaryValue* /* dict */ , |
126 std::string* /* error */, | 152 std::string* /* error */, |
127 bool* /* bad_message */); | 153 bool* /* bad_message */); |
128 std::map<std::string, FactoryMethod> factory_methods; | 154 std::map<std::string, FactoryMethod> factory_methods; |
129 | 155 |
130 WebRequestActionFactory() { | 156 WebRequestActionFactory() { |
131 factory_methods[keys::kAddResponseHeaderType] = | 157 factory_methods[keys::kAddResponseHeaderType] = |
132 &CreateAddResponseHeaderAction; | 158 &CreateAddResponseHeaderAction; |
133 factory_methods[keys::kCancelRequestType] = | 159 factory_methods[keys::kCancelRequestType] = |
134 &CallConstructorFactoryMethod<WebRequestCancelAction>; | 160 &CallConstructorFactoryMethod<WebRequestCancelAction>; |
161 factory_methods[keys::kRedirectByRegExType] = | |
162 &CreateRedirectRequestByRegExAction; | |
135 factory_methods[keys::kRedirectRequestType] = | 163 factory_methods[keys::kRedirectRequestType] = |
136 &CreateRedirectRequestAction; | 164 &CreateRedirectRequestAction; |
137 factory_methods[keys::kRedirectToTransparentImageType] = | 165 factory_methods[keys::kRedirectToTransparentImageType] = |
138 &CallConstructorFactoryMethod< | 166 &CallConstructorFactoryMethod< |
139 WebRequestRedirectToTransparentImageAction>; | 167 WebRequestRedirectToTransparentImageAction>; |
140 factory_methods[keys::kRedirectToEmptyDocumentType] = | 168 factory_methods[keys::kRedirectToEmptyDocumentType] = |
141 &CallConstructorFactoryMethod<WebRequestRedirectToEmptyDocumentAction>; | 169 &CallConstructorFactoryMethod<WebRequestRedirectToEmptyDocumentAction>; |
142 factory_methods[keys::kSetRequestHeaderType] = | 170 factory_methods[keys::kSetRequestHeaderType] = |
143 &CreateSetRequestHeaderAction; | 171 &CreateSetRequestHeaderAction; |
144 factory_methods[keys::kRemoveRequestHeaderType] = | 172 factory_methods[keys::kRemoveRequestHeaderType] = |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 const base::Time& extension_install_time) const { | 405 const base::Time& extension_install_time) const { |
378 CHECK(request_stage & GetStages()); | 406 CHECK(request_stage & GetStages()); |
379 LinkedPtrEventResponseDelta result( | 407 LinkedPtrEventResponseDelta result( |
380 new extension_web_request_api_helpers::EventResponseDelta( | 408 new extension_web_request_api_helpers::EventResponseDelta( |
381 extension_id, extension_install_time)); | 409 extension_id, extension_install_time)); |
382 result->new_url = GURL(kEmptyDocumentUrl); | 410 result->new_url = GURL(kEmptyDocumentUrl); |
383 return result; | 411 return result; |
384 } | 412 } |
385 | 413 |
386 // | 414 // |
415 // WebRequestRedirectByRegExAction | |
416 // | |
417 | |
418 WebRequestRedirectByRegExAction::WebRequestRedirectByRegExAction( | |
419 scoped_ptr<icu::RegexPattern> from_pattern, | |
420 const std::string& to_pattern) | |
421 : from_pattern_(from_pattern.Pass()), | |
422 to_pattern_(to_pattern.data(), to_pattern.size()) {} | |
423 | |
424 WebRequestRedirectByRegExAction::~WebRequestRedirectByRegExAction() {} | |
425 | |
426 // About the syntax of the two languages: | |
427 // | |
428 // ICU (Perl) states: | |
429 // $n The text of capture group n will be substituted for $n. n must be >= 0 | |
430 // and not greater than the number of capture groups. A $ not followed by a | |
431 // digit has no special meaning, and will appear in the substitution text | |
432 // as itself, a $. | |
433 // \ Treat the following character as a literal, suppressing any special | |
434 // meaning. Backslash escaping in substitution text is only required for | |
435 // '$' and '\', but may be used on any other character without bad effects. | |
436 // | |
437 // RE2, derived from RE2::Rewrite() | |
438 // \ May only be followed by a digit or another \. If followed by a single | |
439 // digit, both characters represent the respective capture group. If followed | |
440 // by another \, it is used as an escape sequence. | |
441 | |
442 // static | |
443 std::string WebRequestRedirectByRegExAction::PerlToRe2Style( | |
444 const std::string& perl) { | |
445 std::string::const_iterator i = perl.begin(); | |
446 std::string result; | |
447 while (i != perl.end()) { | |
448 if (*i == '$') { | |
449 ++i; | |
450 if (i == perl.end()) { | |
451 result += '$'; | |
452 } else if (isdigit(*i)) { | |
453 result += '\\'; | |
454 result += *i; | |
455 } else { | |
456 result += '$'; | |
457 result += *i; | |
458 } | |
459 } else if (*i == '\\') { | |
460 ++i; | |
461 if (i == perl.end()) { | |
462 result += '\\'; | |
463 } else if (*i == '$'){ | |
Matt Perry
2012/06/14 18:39:13
nit: space before {
| |
464 result += '$'; | |
465 } else if (*i == '\\'){ | |
Matt Perry
2012/06/14 18:39:13
ditto
| |
466 result += "\\\\"; | |
467 } else { | |
468 result += *i; | |
469 } | |
470 } else { | |
471 result += *i; | |
472 } | |
473 ++i; | |
474 } | |
475 return result; | |
476 } | |
477 | |
478 int WebRequestRedirectByRegExAction::GetStages() const { | |
479 return ON_BEFORE_REQUEST; | |
480 } | |
481 | |
482 WebRequestAction::Type WebRequestRedirectByRegExAction::GetType() const { | |
483 return WebRequestAction::ACTION_REDIRECT_BY_REGEX_DOCUMENT; | |
484 } | |
485 | |
486 LinkedPtrEventResponseDelta WebRequestRedirectByRegExAction::CreateDelta( | |
487 net::URLRequest* request, | |
488 RequestStages request_stage, | |
489 const WebRequestRule::OptionalRequestData& optional_request_data, | |
490 const std::string& extension_id, | |
491 const base::Time& extension_install_time) const { | |
492 CHECK(request_stage & GetStages()); | |
493 CHECK(from_pattern_.get()); | |
494 | |
495 UErrorCode status = U_ZERO_ERROR; | |
496 const std::string& old_url = request->url().spec(); | |
497 icu::UnicodeString old_url_unicode(old_url.data(), old_url.size()); | |
498 | |
499 scoped_ptr<icu::RegexMatcher> matcher( | |
500 from_pattern_->matcher(old_url_unicode, status)); | |
501 if (U_FAILURE(status) || !matcher.get()) | |
502 return LinkedPtrEventResponseDelta(NULL); | |
503 | |
504 icu::UnicodeString new_url = matcher->replaceAll(to_pattern_, status); | |
505 if (U_FAILURE(status)) | |
506 return LinkedPtrEventResponseDelta(NULL); | |
507 | |
508 std::string new_url_utf8; | |
509 UTF16ToUTF8(new_url.getBuffer(), new_url.length(), &new_url_utf8); | |
510 | |
511 if (new_url_utf8 == request->url().spec()) | |
512 return LinkedPtrEventResponseDelta(NULL); | |
513 | |
514 LinkedPtrEventResponseDelta result( | |
515 new extension_web_request_api_helpers::EventResponseDelta( | |
516 extension_id, extension_install_time)); | |
517 result->new_url = GURL(new_url_utf8); | |
518 return result; | |
519 } | |
520 | |
521 // | |
387 // WebRequestSetRequestHeaderAction | 522 // WebRequestSetRequestHeaderAction |
388 // | 523 // |
389 | 524 |
390 WebRequestSetRequestHeaderAction::WebRequestSetRequestHeaderAction( | 525 WebRequestSetRequestHeaderAction::WebRequestSetRequestHeaderAction( |
391 const std::string& name, | 526 const std::string& name, |
392 const std::string& value) | 527 const std::string& value) |
393 : name_(name), | 528 : name_(name), |
394 value_(value) { | 529 value_(value) { |
395 } | 530 } |
396 | 531 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
478 } | 613 } |
479 | 614 |
480 LinkedPtrEventResponseDelta | 615 LinkedPtrEventResponseDelta |
481 WebRequestAddResponseHeaderAction::CreateDelta( | 616 WebRequestAddResponseHeaderAction::CreateDelta( |
482 net::URLRequest* request, | 617 net::URLRequest* request, |
483 RequestStages request_stage, | 618 RequestStages request_stage, |
484 const WebRequestRule::OptionalRequestData& optional_request_data, | 619 const WebRequestRule::OptionalRequestData& optional_request_data, |
485 const std::string& extension_id, | 620 const std::string& extension_id, |
486 const base::Time& extension_install_time) const { | 621 const base::Time& extension_install_time) const { |
487 CHECK(request_stage & GetStages()); | 622 CHECK(request_stage & GetStages()); |
623 net::HttpResponseHeaders* headers = | |
624 optional_request_data.original_response_headers; | |
625 if (!headers) | |
626 return LinkedPtrEventResponseDelta(NULL); | |
627 | |
628 // Don't generate the header if it exists already. | |
629 if (headers->HasHeaderValue(name_, value_)) | |
630 return LinkedPtrEventResponseDelta(NULL); | |
631 | |
488 LinkedPtrEventResponseDelta result( | 632 LinkedPtrEventResponseDelta result( |
489 new extension_web_request_api_helpers::EventResponseDelta( | 633 new extension_web_request_api_helpers::EventResponseDelta( |
490 extension_id, extension_install_time)); | 634 extension_id, extension_install_time)); |
491 | |
492 net::HttpResponseHeaders* headers = | |
493 optional_request_data.original_response_headers; | |
494 if (!headers) | |
495 return result; | |
496 | |
497 // Don't generate the header if it exists already. | |
498 if (headers->HasHeaderValue(name_, value_)) | |
499 return result; | |
500 | |
501 result->added_response_headers.push_back(make_pair(name_, value_)); | 635 result->added_response_headers.push_back(make_pair(name_, value_)); |
502 return result; | 636 return result; |
503 } | 637 } |
504 | 638 |
505 // | 639 // |
506 // WebRequestRemoveResponseHeaderAction | 640 // WebRequestRemoveResponseHeaderAction |
507 // | 641 // |
508 | 642 |
509 WebRequestRemoveResponseHeaderAction::WebRequestRemoveResponseHeaderAction( | 643 WebRequestRemoveResponseHeaderAction::WebRequestRemoveResponseHeaderAction( |
510 const std::string& name, | 644 const std::string& name, |
(...skipping 16 matching lines...) Expand all Loading... | |
527 } | 661 } |
528 | 662 |
529 LinkedPtrEventResponseDelta | 663 LinkedPtrEventResponseDelta |
530 WebRequestRemoveResponseHeaderAction::CreateDelta( | 664 WebRequestRemoveResponseHeaderAction::CreateDelta( |
531 net::URLRequest* request, | 665 net::URLRequest* request, |
532 RequestStages request_stage, | 666 RequestStages request_stage, |
533 const WebRequestRule::OptionalRequestData& optional_request_data, | 667 const WebRequestRule::OptionalRequestData& optional_request_data, |
534 const std::string& extension_id, | 668 const std::string& extension_id, |
535 const base::Time& extension_install_time) const { | 669 const base::Time& extension_install_time) const { |
536 CHECK(request_stage & GetStages()); | 670 CHECK(request_stage & GetStages()); |
671 net::HttpResponseHeaders* headers = | |
672 optional_request_data.original_response_headers; | |
673 if (!headers) | |
674 return LinkedPtrEventResponseDelta(NULL); | |
675 | |
537 LinkedPtrEventResponseDelta result( | 676 LinkedPtrEventResponseDelta result( |
538 new extension_web_request_api_helpers::EventResponseDelta( | 677 new extension_web_request_api_helpers::EventResponseDelta( |
539 extension_id, extension_install_time)); | 678 extension_id, extension_install_time)); |
540 net::HttpResponseHeaders* headers = | |
541 optional_request_data.original_response_headers; | |
542 if (!headers) | |
543 return result; | |
544 void* iter = NULL; | 679 void* iter = NULL; |
545 std::string current_value; | 680 std::string current_value; |
546 while (headers->EnumerateHeader(&iter, name_, ¤t_value)) { | 681 while (headers->EnumerateHeader(&iter, name_, ¤t_value)) { |
547 if (has_value_ && | 682 if (has_value_ && |
548 (current_value.size() != value_.size() || | 683 (current_value.size() != value_.size() || |
549 !std::equal(current_value.begin(), current_value.end(), | 684 !std::equal(current_value.begin(), current_value.end(), |
550 value_.begin(), | 685 value_.begin(), |
551 base::CaseInsensitiveCompare<char>()))) { | 686 base::CaseInsensitiveCompare<char>()))) { |
552 continue; | 687 continue; |
553 } | 688 } |
(...skipping 30 matching lines...) Expand all Loading... | |
584 net::URLRequest* request, | 719 net::URLRequest* request, |
585 RequestStages request_stage, | 720 RequestStages request_stage, |
586 const WebRequestRule::OptionalRequestData& optional_request_data, | 721 const WebRequestRule::OptionalRequestData& optional_request_data, |
587 const std::string& extension_id, | 722 const std::string& extension_id, |
588 const base::Time& extension_install_time) const { | 723 const base::Time& extension_install_time) const { |
589 CHECK(request_stage & GetStages()); | 724 CHECK(request_stage & GetStages()); |
590 return LinkedPtrEventResponseDelta(NULL); | 725 return LinkedPtrEventResponseDelta(NULL); |
591 } | 726 } |
592 | 727 |
593 } // namespace extensions | 728 } // namespace extensions |
OLD | NEW |