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/web_request/web_request_api_helpers.h" | 5 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/string_number_conversions.h" |
8 #include "base/string_util.h" | 9 #include "base/string_util.h" |
9 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
10 #include "base/values.h" | 11 #include "base/values.h" |
11 #include "chrome/browser/extensions/api/web_request/web_request_api.h" | 12 #include "chrome/browser/extensions/api/web_request/web_request_api.h" |
12 #include "chrome/common/url_constants.h" | 13 #include "chrome/common/url_constants.h" |
13 #include "net/base/net_log.h" | 14 #include "net/base/net_log.h" |
| 15 #include "net/cookies/parsed_cookie.h" |
14 #include "net/http/http_util.h" | 16 #include "net/http/http_util.h" |
15 #include "net/url_request/url_request.h" | 17 #include "net/url_request/url_request.h" |
16 | 18 |
17 namespace extension_web_request_api_helpers { | 19 namespace extension_web_request_api_helpers { |
18 | 20 |
19 namespace { | 21 namespace { |
20 | 22 |
| 23 // A ParsedRequestCookie consists of the key and value of the cookie. |
| 24 typedef std::pair<base::StringPiece, base::StringPiece> ParsedRequestCookie; |
| 25 typedef std::vector<ParsedRequestCookie> ParsedRequestCookies; |
| 26 typedef std::vector<linked_ptr<net::ParsedCookie> > ParsedResponseCookies; |
| 27 |
21 static const char* kResourceTypeStrings[] = { | 28 static const char* kResourceTypeStrings[] = { |
22 "main_frame", | 29 "main_frame", |
23 "sub_frame", | 30 "sub_frame", |
24 "stylesheet", | 31 "stylesheet", |
25 "script", | 32 "script", |
26 "image", | 33 "image", |
27 "object", | 34 "object", |
28 "xmlhttprequest", | 35 "xmlhttprequest", |
29 "other", | 36 "other", |
30 "other", | 37 "other", |
(...skipping 15 matching lines...) Expand all Loading... |
46 // entry is no longer required, this should be removed. | 53 // entry is no longer required, this should be removed. |
47 ResourceType::LAST_TYPE, | 54 ResourceType::LAST_TYPE, |
48 }; | 55 }; |
49 | 56 |
50 COMPILE_ASSERT( | 57 COMPILE_ASSERT( |
51 arraysize(kResourceTypeStrings) == arraysize(kResourceTypeValues), | 58 arraysize(kResourceTypeStrings) == arraysize(kResourceTypeValues), |
52 keep_resource_types_in_sync); | 59 keep_resource_types_in_sync); |
53 | 60 |
54 } // namespace | 61 } // namespace |
55 | 62 |
| 63 RequestCookie::RequestCookie() {} |
| 64 RequestCookie::~RequestCookie() {} |
| 65 |
| 66 ResponseCookie::ResponseCookie() {} |
| 67 ResponseCookie::~ResponseCookie() {} |
| 68 |
| 69 RequestCookieModification::RequestCookieModification() {} |
| 70 RequestCookieModification::~RequestCookieModification() {} |
| 71 |
| 72 ResponseCookieModification::ResponseCookieModification() : type(ADD) {} |
| 73 ResponseCookieModification::~ResponseCookieModification() {} |
56 | 74 |
57 EventResponseDelta::EventResponseDelta( | 75 EventResponseDelta::EventResponseDelta( |
58 const std::string& extension_id, const base::Time& extension_install_time) | 76 const std::string& extension_id, const base::Time& extension_install_time) |
59 : extension_id(extension_id), | 77 : extension_id(extension_id), |
60 extension_install_time(extension_install_time), | 78 extension_install_time(extension_install_time), |
61 cancel(false) { | 79 cancel(false) { |
62 } | 80 } |
63 | 81 |
64 EventResponseDelta::~EventResponseDelta() { | 82 EventResponseDelta::~EventResponseDelta() { |
65 } | 83 } |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 // special case as they represent a way of cancelling a request. | 333 // special case as they represent a way of cancelling a request. |
316 if (MergeOnBeforeRequestResponsesHelper( | 334 if (MergeOnBeforeRequestResponsesHelper( |
317 deltas, new_url, conflicting_extensions, net_log, true)) { | 335 deltas, new_url, conflicting_extensions, net_log, true)) { |
318 // If any extension cancelled a request by redirecting to a data:// URL or | 336 // If any extension cancelled a request by redirecting to a data:// URL or |
319 // about:blank, we don't consider the other redirects. | 337 // about:blank, we don't consider the other redirects. |
320 return; | 338 return; |
321 } | 339 } |
322 | 340 |
323 // Handle all other redirects. | 341 // Handle all other redirects. |
324 MergeOnBeforeRequestResponsesHelper( | 342 MergeOnBeforeRequestResponsesHelper( |
325 deltas, new_url, conflicting_extensions, net_log, false); | 343 deltas, new_url, conflicting_extensions, net_log, false); |
| 344 } |
| 345 |
| 346 // Assumes that |header_value| is the cookie header value of a HTTP Request |
| 347 // following the cookie-string schema of RFC 6265, section 4.2.1, and returns |
| 348 // cookie name/value pairs. If cookie values are presented in double quotes, |
| 349 // these will appear in |parsed| as well. We can assume that the cookie header |
| 350 // is written by Chromium and therefore, well-formed. |
| 351 static void ParseRequestCookieLine( |
| 352 const std::string& header_value, |
| 353 ParsedRequestCookies* parsed_cookies) { |
| 354 std::string::const_iterator i = header_value.begin(); |
| 355 while (i != header_value.end()) { |
| 356 // Here we are at the beginning of a cookie. |
| 357 |
| 358 // Eat whitespace. |
| 359 while (i != header_value.end() && *i == ' ') ++i; |
| 360 if (i == header_value.end()) return; |
| 361 |
| 362 // Find cookie name. |
| 363 std::string::const_iterator cookie_name_beginning = i; |
| 364 while (i != header_value.end() && *i != '=') ++i; |
| 365 base::StringPiece cookie_name(cookie_name_beginning, i); |
| 366 |
| 367 // Find cookie value. |
| 368 base::StringPiece cookie_value; |
| 369 if (i != header_value.end()) { // Cookies may have no value. |
| 370 ++i; // Skip '='. |
| 371 std::string::const_iterator cookie_value_beginning = i; |
| 372 if (*i == '"') { |
| 373 while (i != header_value.end() && *i != '"') ++i; |
| 374 if (i == header_value.end()) return; |
| 375 ++i; // Skip '"'. |
| 376 cookie_value = base::StringPiece(cookie_value_beginning, i); |
| 377 // i points to character after '"', potentially a ';' |
| 378 } else { |
| 379 while (i != header_value.end() && *i != ';') ++i; |
| 380 cookie_value = base::StringPiece(cookie_value_beginning, i); |
| 381 // i points to ';' or end of string. |
| 382 } |
| 383 } |
| 384 parsed_cookies->push_back(make_pair(cookie_name, cookie_value)); |
| 385 // Eat ';' |
| 386 if (i != header_value.end()) ++i; |
| 387 } |
| 388 } |
| 389 |
| 390 // Writes all cookies of |parsed_cookies| into a HTTP Request header value |
| 391 // that belongs to the "Cookie" header. |
| 392 static std::string SerializeRequestCookieLine( |
| 393 const ParsedRequestCookies& parsed_cookies) { |
| 394 std::string buffer; |
| 395 for (ParsedRequestCookies::const_iterator i = parsed_cookies.begin(); |
| 396 i != parsed_cookies.end(); ++i) { |
| 397 if (!buffer.empty()) |
| 398 buffer += "; "; |
| 399 buffer += i->first.as_string(); |
| 400 if (!i->second.empty()) |
| 401 buffer += "=" + i->second.as_string(); |
| 402 } |
| 403 return buffer; |
| 404 } |
| 405 |
| 406 static bool DoesRequestCookieMatchFilter( |
| 407 const ParsedRequestCookie& cookie, |
| 408 RequestCookie* filter) { |
| 409 if (!filter) return true; |
| 410 if (filter->name.get() && cookie.first != *filter->name) return false; |
| 411 if (filter->value.get() && cookie.second != *filter->value) return false; |
| 412 return true; |
| 413 } |
| 414 |
| 415 // Applies all CookieModificationType::ADD operations for request cookies of |
| 416 // |deltas| to |cookies|. Returns whether any cookie was added. |
| 417 static bool MergeAddRequestCookieModifications( |
| 418 const EventResponseDeltas& deltas, |
| 419 ParsedRequestCookies* cookies) { |
| 420 bool modified = false; |
| 421 // We assume here that the deltas are sorted in decreasing extension |
| 422 // precedence (i.e. decreasing extension installation time). |
| 423 EventResponseDeltas::const_reverse_iterator delta; |
| 424 for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) { |
| 425 const RequestCookieModifications& modifications = |
| 426 (*delta)->request_cookie_modifications; |
| 427 for (RequestCookieModifications::const_iterator mod = modifications.begin(); |
| 428 mod != modifications.end(); ++mod) { |
| 429 if ((*mod)->type != ADD || !(*mod)->modification.get()) |
| 430 continue; |
| 431 std::string* new_name = (*mod)->modification->name.get(); |
| 432 std::string* new_value = (*mod)->modification->value.get(); |
| 433 if (!new_name || !new_value) |
| 434 continue; |
| 435 |
| 436 bool cookie_with_same_name_found = false; |
| 437 for (ParsedRequestCookies::iterator cookie = cookies->begin(); |
| 438 cookie != cookies->end() && !cookie_with_same_name_found; ++cookie) { |
| 439 if (cookie->first == *new_name) { |
| 440 if (cookie->second != *new_value) { |
| 441 cookie->second = *new_value; |
| 442 modified = true; |
| 443 } |
| 444 cookie_with_same_name_found = true; |
| 445 } |
| 446 } |
| 447 if (!cookie_with_same_name_found) { |
| 448 cookies->push_back(std::make_pair(base::StringPiece(*new_name), |
| 449 base::StringPiece(*new_value))); |
| 450 modified = true; |
| 451 } |
| 452 } |
| 453 } |
| 454 return modified; |
| 455 } |
| 456 |
| 457 // Applies all CookieModificationType::EDIT operations for request cookies of |
| 458 // |deltas| to |cookies|. Returns whether any cookie was modified. |
| 459 static bool MergeEditRequestCookieModifications( |
| 460 const EventResponseDeltas& deltas, |
| 461 ParsedRequestCookies* cookies) { |
| 462 bool modified = false; |
| 463 // We assume here that the deltas are sorted in decreasing extension |
| 464 // precedence (i.e. decreasing extension installation time). |
| 465 EventResponseDeltas::const_reverse_iterator delta; |
| 466 for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) { |
| 467 const RequestCookieModifications& modifications = |
| 468 (*delta)->request_cookie_modifications; |
| 469 for (RequestCookieModifications::const_iterator mod = modifications.begin(); |
| 470 mod != modifications.end(); ++mod) { |
| 471 if ((*mod)->type != EDIT || !(*mod)->modification.get()) |
| 472 continue; |
| 473 |
| 474 std::string* new_value = (*mod)->modification->value.get(); |
| 475 RequestCookie* filter = (*mod)->filter.get(); |
| 476 for (ParsedRequestCookies::iterator cookie = cookies->begin(); |
| 477 cookie != cookies->end(); ++cookie) { |
| 478 if (!DoesRequestCookieMatchFilter(*cookie, filter)) |
| 479 continue; |
| 480 // If the edit operation tries to modify the cookie name, we just ignore |
| 481 // this. We only modify the cookie value. |
| 482 if (new_value && cookie->second != *new_value) { |
| 483 cookie->second = *new_value; |
| 484 modified = true; |
| 485 } |
| 486 } |
| 487 } |
| 488 } |
| 489 return modified; |
| 490 } |
| 491 |
| 492 // Applies all CookieModificationType::REMOVE operations for request cookies of |
| 493 // |deltas| to |cookies|. Returns whether any cookie was deleted. |
| 494 static bool MergeRemoveRequestCookieModifications( |
| 495 const EventResponseDeltas& deltas, |
| 496 ParsedRequestCookies* cookies) { |
| 497 bool modified = false; |
| 498 // We assume here that the deltas are sorted in decreasing extension |
| 499 // precedence (i.e. decreasing extension installation time). |
| 500 EventResponseDeltas::const_reverse_iterator delta; |
| 501 for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) { |
| 502 const RequestCookieModifications& modifications = |
| 503 (*delta)->request_cookie_modifications; |
| 504 for (RequestCookieModifications::const_iterator mod = modifications.begin(); |
| 505 mod != modifications.end(); ++mod) { |
| 506 if ((*mod)->type != REMOVE) |
| 507 continue; |
| 508 |
| 509 RequestCookie* filter = (*mod)->filter.get(); |
| 510 ParsedRequestCookies::iterator i = cookies->begin(); |
| 511 while (i != cookies->end()) { |
| 512 if (DoesRequestCookieMatchFilter(*i, filter)) { |
| 513 i = cookies->erase(i); |
| 514 modified = true; |
| 515 } else { |
| 516 ++i; |
| 517 } |
| 518 } |
| 519 } |
| 520 } |
| 521 return modified; |
| 522 } |
| 523 |
| 524 void MergeCookiesInOnBeforeSendHeadersResponses( |
| 525 const EventResponseDeltas& deltas, |
| 526 net::HttpRequestHeaders* request_headers, |
| 527 std::set<std::string>* conflicting_extensions, |
| 528 const net::BoundNetLog* net_log) { |
| 529 // Skip all work if there are no registered cookie modifications. |
| 530 bool cookie_modifications_exist = false; |
| 531 EventResponseDeltas::const_iterator delta; |
| 532 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 533 cookie_modifications_exist |= |
| 534 !(*delta)->request_cookie_modifications.empty(); |
| 535 } |
| 536 if (!cookie_modifications_exist) |
| 537 return; |
| 538 |
| 539 // Parse old cookie line. |
| 540 std::string cookie_header; |
| 541 request_headers->GetHeader(net::HttpRequestHeaders::kCookie, &cookie_header); |
| 542 ParsedRequestCookies cookies; |
| 543 ParseRequestCookieLine(cookie_header, &cookies); |
| 544 |
| 545 // Modify cookies. |
| 546 bool modified = false; |
| 547 modified |= MergeAddRequestCookieModifications(deltas, &cookies); |
| 548 modified |= MergeEditRequestCookieModifications(deltas, &cookies); |
| 549 modified |= MergeRemoveRequestCookieModifications(deltas, &cookies); |
| 550 |
| 551 // Reassemble and store new cookie line. |
| 552 if (modified) { |
| 553 std::string new_cookie_header = SerializeRequestCookieLine(cookies); |
| 554 request_headers->SetHeader(net::HttpRequestHeaders::kCookie, |
| 555 new_cookie_header); |
| 556 } |
326 } | 557 } |
327 | 558 |
328 void MergeOnBeforeSendHeadersResponses( | 559 void MergeOnBeforeSendHeadersResponses( |
329 const EventResponseDeltas& deltas, | 560 const EventResponseDeltas& deltas, |
330 net::HttpRequestHeaders* request_headers, | 561 net::HttpRequestHeaders* request_headers, |
331 std::set<std::string>* conflicting_extensions, | 562 std::set<std::string>* conflicting_extensions, |
332 const net::BoundNetLog* net_log) { | 563 const net::BoundNetLog* net_log) { |
333 EventResponseDeltas::const_iterator delta; | 564 EventResponseDeltas::const_iterator delta; |
334 | 565 |
335 // Here we collect which headers we have removed or set to new values | 566 // Here we collect which headers we have removed or set to new values |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 net_log->AddEvent( | 642 net_log->AddEvent( |
412 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, | 643 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, |
413 base::Bind(&NetLogModificationCallback, delta->get())); | 644 base::Bind(&NetLogModificationCallback, delta->get())); |
414 } else { | 645 } else { |
415 conflicting_extensions->insert((*delta)->extension_id); | 646 conflicting_extensions->insert((*delta)->extension_id); |
416 net_log->AddEvent( | 647 net_log->AddEvent( |
417 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 648 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
418 CreateNetLogExtensionIdCallback(delta->get())); | 649 CreateNetLogExtensionIdCallback(delta->get())); |
419 } | 650 } |
420 } | 651 } |
| 652 |
| 653 MergeCookiesInOnBeforeSendHeadersResponses(deltas, request_headers, |
| 654 conflicting_extensions, net_log); |
| 655 } |
| 656 |
| 657 // Retrives all cookies from |override_response_headers|. |
| 658 static ParsedResponseCookies GetResponseCookies( |
| 659 scoped_refptr<net::HttpResponseHeaders> override_response_headers) { |
| 660 ParsedResponseCookies result; |
| 661 |
| 662 void* iter = NULL; |
| 663 std::string value; |
| 664 while (override_response_headers->EnumerateHeader(&iter, "Set-Cookie", |
| 665 &value)) { |
| 666 result.push_back(make_linked_ptr(new net::ParsedCookie(value))); |
| 667 } |
| 668 return result; |
| 669 } |
| 670 |
| 671 // Stores all |cookies| in |override_response_headers| deleting previously |
| 672 // existing cookie definitions. |
| 673 static void StoreResponseCookies( |
| 674 const ParsedResponseCookies& cookies, |
| 675 scoped_refptr<net::HttpResponseHeaders> override_response_headers) { |
| 676 override_response_headers->RemoveHeader("Set-Cookie"); |
| 677 for (ParsedResponseCookies::const_iterator i = cookies.begin(); |
| 678 i != cookies.end(); ++i) { |
| 679 override_response_headers->AddHeader("Set-Cookie: " + (*i)->ToCookieLine()); |
| 680 } |
| 681 } |
| 682 |
| 683 // Modifies |cookie| according to |modification|. Each value that is set in |
| 684 // |modification| is applied to |cookie|. |
| 685 static bool ApplyResponseCookieModification(ResponseCookie* modification, |
| 686 net::ParsedCookie* cookie) { |
| 687 bool modified = false; |
| 688 if (modification->name.get()) |
| 689 modified |= cookie->SetName(*modification->name); |
| 690 if (modification->value.get()) |
| 691 modified |= cookie->SetValue(*modification->value); |
| 692 if (modification->expires.get()) |
| 693 modified |= cookie->SetExpires(*modification->expires); |
| 694 if (modification->max_age.get()) |
| 695 modified |= cookie->SetMaxAge(base::IntToString(*modification->max_age)); |
| 696 if (modification->domain.get()) |
| 697 modified |= cookie->SetDomain(*modification->domain); |
| 698 if (modification->path.get()) |
| 699 modified |= cookie->SetPath(*modification->path); |
| 700 if (modification->secure.get()) |
| 701 modified |= cookie->SetIsSecure(*modification->secure); |
| 702 if (modification->http_only.get()) |
| 703 modified |= cookie->SetIsHttpOnly(*modification->http_only); |
| 704 return modified; |
| 705 } |
| 706 |
| 707 static bool DoesResponseCookieMatchFilter(net::ParsedCookie* cookie, |
| 708 ResponseCookie* filter) { |
| 709 if (!cookie->IsValid()) return false; |
| 710 if (!filter) return true; |
| 711 if (filter->name.get() && cookie->Name() != *filter->name) return false; |
| 712 if (filter->value.get() && cookie->Value() != *filter->value) return false; |
| 713 if (filter->expires.get()) { |
| 714 std::string actual_value = cookie->HasExpires() ? cookie->Expires() : ""; |
| 715 if (actual_value != *filter->expires) |
| 716 return false; |
| 717 } |
| 718 if (filter->max_age.get()) { |
| 719 std::string actual_value = cookie->HasMaxAge() ? cookie->MaxAge() : ""; |
| 720 if (actual_value != base::IntToString(*filter->max_age)) |
| 721 return false; |
| 722 } |
| 723 if (filter->domain.get()) { |
| 724 std::string actual_value = cookie->HasDomain() ? cookie->Domain() : ""; |
| 725 if (actual_value != *filter->domain) |
| 726 return false; |
| 727 } |
| 728 if (filter->path.get()) { |
| 729 std::string actual_value = cookie->HasPath() ? cookie->Path() : ""; |
| 730 if (actual_value != *filter->path) |
| 731 return false; |
| 732 } |
| 733 if (filter->secure.get() && cookie->IsSecure() != *filter->secure) |
| 734 return false; |
| 735 if (filter->http_only.get() && cookie->IsHttpOnly() != *filter->http_only) |
| 736 return false; |
| 737 return true; |
| 738 } |
| 739 |
| 740 // Applies all CookieModificationType::ADD operations for response cookies of |
| 741 // |deltas| to |cookies|. Returns whether any cookie was added. |
| 742 static bool MergeAddResponseCookieModifications( |
| 743 const EventResponseDeltas& deltas, |
| 744 ParsedResponseCookies* cookies) { |
| 745 bool modified = false; |
| 746 // We assume here that the deltas are sorted in decreasing extension |
| 747 // precedence (i.e. decreasing extension installation time). |
| 748 EventResponseDeltas::const_reverse_iterator delta; |
| 749 for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) { |
| 750 const ResponseCookieModifications& modifications = |
| 751 (*delta)->response_cookie_modifications; |
| 752 for (ResponseCookieModifications::const_iterator mod = |
| 753 modifications.begin(); mod != modifications.end(); ++mod) { |
| 754 if ((*mod)->type != ADD || !(*mod)->modification.get()) |
| 755 continue; |
| 756 // Cookie names are not unique in response cookies so we always append |
| 757 // and never override. |
| 758 linked_ptr<net::ParsedCookie> cookie(new net::ParsedCookie("")); |
| 759 ApplyResponseCookieModification((*mod)->modification.get(), cookie.get()); |
| 760 cookies->push_back(cookie); |
| 761 modified = true; |
| 762 } |
| 763 } |
| 764 return modified; |
| 765 } |
| 766 |
| 767 // Applies all CookieModificationType::EDIT operations for response cookies of |
| 768 // |deltas| to |cookies|. Returns whether any cookie was modified. |
| 769 static bool MergeEditResponseCookieModifications( |
| 770 const EventResponseDeltas& deltas, |
| 771 ParsedResponseCookies* cookies) { |
| 772 bool modified = false; |
| 773 // We assume here that the deltas are sorted in decreasing extension |
| 774 // precedence (i.e. decreasing extension installation time). |
| 775 EventResponseDeltas::const_reverse_iterator delta; |
| 776 for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) { |
| 777 const ResponseCookieModifications& modifications = |
| 778 (*delta)->response_cookie_modifications; |
| 779 for (ResponseCookieModifications::const_iterator mod = |
| 780 modifications.begin(); mod != modifications.end(); ++mod) { |
| 781 if ((*mod)->type != EDIT || !(*mod)->modification.get()) |
| 782 continue; |
| 783 |
| 784 for (ParsedResponseCookies::iterator cookie = cookies->begin(); |
| 785 cookie != cookies->end(); ++cookie) { |
| 786 if (DoesResponseCookieMatchFilter(cookie->get(), |
| 787 (*mod)->filter.get())) { |
| 788 modified |= ApplyResponseCookieModification( |
| 789 (*mod)->modification.get(), cookie->get()); |
| 790 } |
| 791 } |
| 792 } |
| 793 } |
| 794 return modified; |
| 795 } |
| 796 |
| 797 // Applies all CookieModificationType::REMOVE operations for response cookies of |
| 798 // |deltas| to |cookies|. Returns whether any cookie was deleted. |
| 799 static bool MergeRemoveResponseCookieModifications( |
| 800 const EventResponseDeltas& deltas, |
| 801 ParsedResponseCookies* cookies) { |
| 802 bool modified = false; |
| 803 // We assume here that the deltas are sorted in decreasing extension |
| 804 // precedence (i.e. decreasing extension installation time). |
| 805 EventResponseDeltas::const_reverse_iterator delta; |
| 806 for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) { |
| 807 const ResponseCookieModifications& modifications = |
| 808 (*delta)->response_cookie_modifications; |
| 809 for (ResponseCookieModifications::const_iterator mod = |
| 810 modifications.begin(); mod != modifications.end(); ++mod) { |
| 811 if ((*mod)->type != REMOVE) |
| 812 continue; |
| 813 |
| 814 ParsedResponseCookies::iterator i = cookies->begin(); |
| 815 while (i != cookies->end()) { |
| 816 if (DoesResponseCookieMatchFilter(i->get(), |
| 817 (*mod)->filter.get())) { |
| 818 i = cookies->erase(i); |
| 819 modified = true; |
| 820 } else { |
| 821 ++i; |
| 822 } |
| 823 } |
| 824 } |
| 825 } |
| 826 return modified; |
| 827 } |
| 828 |
| 829 void MergeCookiesInOnHeadersReceivedResponses( |
| 830 const EventResponseDeltas& deltas, |
| 831 const net::HttpResponseHeaders* original_response_headers, |
| 832 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, |
| 833 std::set<std::string>* conflicting_extensions, |
| 834 const net::BoundNetLog* net_log) { |
| 835 // Skip all work if there are no registered cookie modifications. |
| 836 bool cookie_modifications_exist = false; |
| 837 EventResponseDeltas::const_reverse_iterator delta; |
| 838 for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) { |
| 839 cookie_modifications_exist |= |
| 840 !(*delta)->response_cookie_modifications.empty(); |
| 841 } |
| 842 if (!cookie_modifications_exist) |
| 843 return; |
| 844 |
| 845 // Only create a copy if we really want to modify the response headers. |
| 846 if (override_response_headers->get() == NULL) { |
| 847 *override_response_headers = new net::HttpResponseHeaders( |
| 848 original_response_headers->raw_headers()); |
| 849 } |
| 850 |
| 851 ParsedResponseCookies cookies = |
| 852 GetResponseCookies(*override_response_headers); |
| 853 |
| 854 bool modified = false; |
| 855 modified |= MergeAddResponseCookieModifications(deltas, &cookies); |
| 856 modified |= MergeEditResponseCookieModifications(deltas, &cookies); |
| 857 modified |= MergeRemoveResponseCookieModifications(deltas, &cookies); |
| 858 |
| 859 // Store new value. |
| 860 if (modified) |
| 861 StoreResponseCookies(cookies, *override_response_headers); |
421 } | 862 } |
422 | 863 |
423 // Converts the key of the (key, value) pair to lower case. | 864 // Converts the key of the (key, value) pair to lower case. |
424 static ResponseHeader ToLowerCase(const ResponseHeader& header) { | 865 static ResponseHeader ToLowerCase(const ResponseHeader& header) { |
425 std::string lower_key(header.first); | 866 std::string lower_key(header.first); |
426 StringToLowerASCII(&lower_key); | 867 StringToLowerASCII(&lower_key); |
427 return ResponseHeader(lower_key, header.second); | 868 return ResponseHeader(lower_key, header.second); |
428 } | 869 } |
429 | 870 |
430 void MergeOnHeadersReceivedResponses( | 871 void MergeOnHeadersReceivedResponses( |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 net_log->AddEvent( | 936 net_log->AddEvent( |
496 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, | 937 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, |
497 CreateNetLogExtensionIdCallback(delta->get())); | 938 CreateNetLogExtensionIdCallback(delta->get())); |
498 } else { | 939 } else { |
499 conflicting_extensions->insert((*delta)->extension_id); | 940 conflicting_extensions->insert((*delta)->extension_id); |
500 net_log->AddEvent( | 941 net_log->AddEvent( |
501 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 942 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
502 CreateNetLogExtensionIdCallback(delta->get())); | 943 CreateNetLogExtensionIdCallback(delta->get())); |
503 } | 944 } |
504 } | 945 } |
| 946 |
| 947 MergeCookiesInOnHeadersReceivedResponses(deltas, original_response_headers, |
| 948 override_response_headers, conflicting_extensions, net_log); |
505 } | 949 } |
506 | 950 |
507 bool MergeOnAuthRequiredResponses( | 951 bool MergeOnAuthRequiredResponses( |
508 const EventResponseDeltas& deltas, | 952 const EventResponseDeltas& deltas, |
509 net::AuthCredentials* auth_credentials, | 953 net::AuthCredentials* auth_credentials, |
510 std::set<std::string>* conflicting_extensions, | 954 std::set<std::string>* conflicting_extensions, |
511 const net::BoundNetLog* net_log) { | 955 const net::BoundNetLog* net_log) { |
512 CHECK(auth_credentials); | 956 CHECK(auth_credentials); |
513 bool credentials_set = false; | 957 bool credentials_set = false; |
514 | 958 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 | 1011 |
568 bool CanExtensionAccessURL(const extensions::Extension* extension, | 1012 bool CanExtensionAccessURL(const extensions::Extension* extension, |
569 const GURL& url) { | 1013 const GURL& url) { |
570 // about: URLs are not covered in host permissions, but are allowed anyway. | 1014 // about: URLs are not covered in host permissions, but are allowed anyway. |
571 return (url.SchemeIs(chrome::kAboutScheme) || | 1015 return (url.SchemeIs(chrome::kAboutScheme) || |
572 extension->HasHostPermission(url) || | 1016 extension->HasHostPermission(url) || |
573 url.GetOrigin() == extension->url()); | 1017 url.GetOrigin() == extension->url()); |
574 } | 1018 } |
575 | 1019 |
576 } // namespace extension_web_request_api_helpers | 1020 } // namespace extension_web_request_api_helpers |
OLD | NEW |