Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc

Issue 10449069: Support redirects by regular expression in declarative WebRequest API (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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_, &current_value)) { 681 while (headers->EnumerateHeader(&iter, name_, &current_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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698