| 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 <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/string_number_conversions.h" | 10 #include "base/string_number_conversions.h" |
| 11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 12 #include "base/stringprintf.h" | 12 #include "base/stringprintf.h" |
| 13 #include "base/time.h" | 13 #include "base/time.h" |
| 14 #include "base/values.h" | 14 #include "base/values.h" |
| 15 #include "chrome/browser/extensions/api/web_request/web_request_api.h" | 15 #include "chrome/browser/extensions/api/web_request/web_request_api.h" |
| 16 #include "chrome/browser/extensions/extension_warning_set.h" |
| 16 #include "chrome/browser/renderer_host/web_cache_manager.h" | 17 #include "chrome/browser/renderer_host/web_cache_manager.h" |
| 17 #include "chrome/common/url_constants.h" | 18 #include "chrome/common/url_constants.h" |
| 18 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
| 19 #include "net/base/net_log.h" | 20 #include "net/base/net_log.h" |
| 20 #include "net/cookies/cookie_util.h" | 21 #include "net/cookies/cookie_util.h" |
| 21 #include "net/cookies/parsed_cookie.h" | 22 #include "net/cookies/parsed_cookie.h" |
| 22 #include "net/http/http_util.h" | 23 #include "net/http/http_util.h" |
| 23 #include "net/url_request/url_request.h" | 24 #include "net/url_request/url_request.h" |
| 24 | 25 |
| 26 // TODO(battre): move all static functions into an anonymous namespace at the |
| 27 // top of this file. |
| 28 |
| 25 using base::Time; | 29 using base::Time; |
| 30 using extensions::ExtensionWarning; |
| 26 | 31 |
| 27 namespace extension_web_request_api_helpers { | 32 namespace extension_web_request_api_helpers { |
| 28 | 33 |
| 29 namespace { | 34 namespace { |
| 30 | 35 |
| 31 // A ParsedRequestCookie consists of the key and value of the cookie. | 36 // A ParsedRequestCookie consists of the key and value of the cookie. |
| 32 typedef std::pair<base::StringPiece, base::StringPiece> ParsedRequestCookie; | 37 typedef std::pair<base::StringPiece, base::StringPiece> ParsedRequestCookie; |
| 33 typedef std::vector<ParsedRequestCookie> ParsedRequestCookies; | 38 typedef std::vector<ParsedRequestCookie> ParsedRequestCookies; |
| 34 typedef std::vector<linked_ptr<net::ParsedCookie> > ParsedResponseCookies; | 39 typedef std::vector<linked_ptr<net::ParsedCookie> > ParsedResponseCookies; |
| 35 | 40 |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 // Helper function for MergeOnBeforeRequestResponses() that allows ignoring | 327 // Helper function for MergeOnBeforeRequestResponses() that allows ignoring |
| 323 // all redirects but those to data:// urls and about:blank. This is important | 328 // all redirects but those to data:// urls and about:blank. This is important |
| 324 // to treat these URLs as "cancel urls", i.e. URLs that extensions redirect | 329 // to treat these URLs as "cancel urls", i.e. URLs that extensions redirect |
| 325 // to if they want to express that they want to cancel a request. This reduces | 330 // to if they want to express that they want to cancel a request. This reduces |
| 326 // the number of conflicts that we need to flag, as canceling is considered | 331 // the number of conflicts that we need to flag, as canceling is considered |
| 327 // a higher precedence operation that redirects. | 332 // a higher precedence operation that redirects. |
| 328 // Returns whether a redirect occurred. | 333 // Returns whether a redirect occurred. |
| 329 static bool MergeOnBeforeRequestResponsesHelper( | 334 static bool MergeOnBeforeRequestResponsesHelper( |
| 330 const EventResponseDeltas& deltas, | 335 const EventResponseDeltas& deltas, |
| 331 GURL* new_url, | 336 GURL* new_url, |
| 332 std::set<std::string>* conflicting_extensions, | 337 extensions::ExtensionWarningSet* conflicting_extensions, |
| 333 const net::BoundNetLog* net_log, | 338 const net::BoundNetLog* net_log, |
| 334 bool consider_only_cancel_scheme_urls) { | 339 bool consider_only_cancel_scheme_urls) { |
| 335 bool redirected = false; | 340 bool redirected = false; |
| 336 | 341 |
| 342 // Extension that determines the |new_url|. |
| 343 std::string winning_extension_id; |
| 337 EventResponseDeltas::const_iterator delta; | 344 EventResponseDeltas::const_iterator delta; |
| 338 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { | 345 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 339 if ((*delta)->new_url.is_empty()) | 346 if ((*delta)->new_url.is_empty()) |
| 340 continue; | 347 continue; |
| 341 if (consider_only_cancel_scheme_urls && | 348 if (consider_only_cancel_scheme_urls && |
| 342 !(*delta)->new_url.SchemeIs(chrome::kDataScheme) && | 349 !(*delta)->new_url.SchemeIs(chrome::kDataScheme) && |
| 343 (*delta)->new_url.spec() != "about:blank") { | 350 (*delta)->new_url.spec() != "about:blank") { |
| 344 continue; | 351 continue; |
| 345 } | 352 } |
| 346 | 353 |
| 347 if (!redirected || *new_url == (*delta)->new_url) { | 354 if (!redirected || *new_url == (*delta)->new_url) { |
| 348 *new_url = (*delta)->new_url; | 355 *new_url = (*delta)->new_url; |
| 356 winning_extension_id = (*delta)->extension_id; |
| 349 redirected = true; | 357 redirected = true; |
| 350 net_log->AddEvent( | 358 net_log->AddEvent( |
| 351 net::NetLog::TYPE_CHROME_EXTENSION_REDIRECTED_REQUEST, | 359 net::NetLog::TYPE_CHROME_EXTENSION_REDIRECTED_REQUEST, |
| 352 CreateNetLogExtensionIdCallback(delta->get())); | 360 CreateNetLogExtensionIdCallback(delta->get())); |
| 353 } else { | 361 } else { |
| 354 conflicting_extensions->insert((*delta)->extension_id); | 362 conflicting_extensions->insert( |
| 363 ExtensionWarning::CreateRedirectConflictWarning( |
| 364 (*delta)->extension_id, |
| 365 winning_extension_id, |
| 366 (*delta)->new_url, |
| 367 *new_url)); |
| 355 net_log->AddEvent( | 368 net_log->AddEvent( |
| 356 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 369 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
| 357 CreateNetLogExtensionIdCallback(delta->get())); | 370 CreateNetLogExtensionIdCallback(delta->get())); |
| 358 } | 371 } |
| 359 } | 372 } |
| 360 return redirected; | 373 return redirected; |
| 361 } | 374 } |
| 362 | 375 |
| 363 void MergeOnBeforeRequestResponses( | 376 void MergeOnBeforeRequestResponses( |
| 364 const EventResponseDeltas& deltas, | 377 const EventResponseDeltas& deltas, |
| 365 GURL* new_url, | 378 GURL* new_url, |
| 366 std::set<std::string>* conflicting_extensions, | 379 extensions::ExtensionWarningSet* conflicting_extensions, |
| 367 const net::BoundNetLog* net_log) { | 380 const net::BoundNetLog* net_log) { |
| 368 | 381 |
| 369 // First handle only redirects to data:// URLs and about:blank. These are a | 382 // First handle only redirects to data:// URLs and about:blank. These are a |
| 370 // special case as they represent a way of cancelling a request. | 383 // special case as they represent a way of cancelling a request. |
| 371 if (MergeOnBeforeRequestResponsesHelper( | 384 if (MergeOnBeforeRequestResponsesHelper( |
| 372 deltas, new_url, conflicting_extensions, net_log, true)) { | 385 deltas, new_url, conflicting_extensions, net_log, true)) { |
| 373 // If any extension cancelled a request by redirecting to a data:// URL or | 386 // If any extension cancelled a request by redirecting to a data:// URL or |
| 374 // about:blank, we don't consider the other redirects. | 387 // about:blank, we don't consider the other redirects. |
| 375 return; | 388 return; |
| 376 } | 389 } |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 } | 567 } |
| 555 } | 568 } |
| 556 } | 569 } |
| 557 } | 570 } |
| 558 return modified; | 571 return modified; |
| 559 } | 572 } |
| 560 | 573 |
| 561 void MergeCookiesInOnBeforeSendHeadersResponses( | 574 void MergeCookiesInOnBeforeSendHeadersResponses( |
| 562 const EventResponseDeltas& deltas, | 575 const EventResponseDeltas& deltas, |
| 563 net::HttpRequestHeaders* request_headers, | 576 net::HttpRequestHeaders* request_headers, |
| 564 std::set<std::string>* conflicting_extensions, | 577 extensions::ExtensionWarningSet* conflicting_extensions, |
| 565 const net::BoundNetLog* net_log) { | 578 const net::BoundNetLog* net_log) { |
| 566 // Skip all work if there are no registered cookie modifications. | 579 // Skip all work if there are no registered cookie modifications. |
| 567 bool cookie_modifications_exist = false; | 580 bool cookie_modifications_exist = false; |
| 568 EventResponseDeltas::const_iterator delta; | 581 EventResponseDeltas::const_iterator delta; |
| 569 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { | 582 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 570 cookie_modifications_exist |= | 583 cookie_modifications_exist |= |
| 571 !(*delta)->request_cookie_modifications.empty(); | 584 !(*delta)->request_cookie_modifications.empty(); |
| 572 } | 585 } |
| 573 if (!cookie_modifications_exist) | 586 if (!cookie_modifications_exist) |
| 574 return; | 587 return; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 586 modified |= MergeRemoveRequestCookieModifications(deltas, &cookies); | 599 modified |= MergeRemoveRequestCookieModifications(deltas, &cookies); |
| 587 | 600 |
| 588 // Reassemble and store new cookie line. | 601 // Reassemble and store new cookie line. |
| 589 if (modified) { | 602 if (modified) { |
| 590 std::string new_cookie_header = SerializeRequestCookieLine(cookies); | 603 std::string new_cookie_header = SerializeRequestCookieLine(cookies); |
| 591 request_headers->SetHeader(net::HttpRequestHeaders::kCookie, | 604 request_headers->SetHeader(net::HttpRequestHeaders::kCookie, |
| 592 new_cookie_header); | 605 new_cookie_header); |
| 593 } | 606 } |
| 594 } | 607 } |
| 595 | 608 |
| 609 // Returns the extension ID of the first extension in |deltas| that sets the |
| 610 // request header identified by |key| to |value|. |
| 611 static std::string FindSetRequestHeader( |
| 612 const EventResponseDeltas& deltas, |
| 613 const std::string& key, |
| 614 const std::string& value) { |
| 615 EventResponseDeltas::const_iterator delta; |
| 616 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 617 net::HttpRequestHeaders::Iterator modification( |
| 618 (*delta)->modified_request_headers); |
| 619 while (modification.GetNext()) { |
| 620 if (key == modification.name() && value == modification.value()) |
| 621 return (*delta)->extension_id; |
| 622 } |
| 623 } |
| 624 return ""; |
| 625 } |
| 626 |
| 627 // Returns the extension ID of the first extension in |deltas| that removes the |
| 628 // request header identified by |key|. |
| 629 static std::string FindRemoveRequestHeader( |
| 630 const EventResponseDeltas& deltas, |
| 631 const std::string& key) { |
| 632 EventResponseDeltas::const_iterator delta; |
| 633 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 634 std::vector<std::string>::iterator i; |
| 635 for (i = (*delta)->deleted_request_headers.begin(); |
| 636 i != (*delta)->deleted_request_headers.end(); |
| 637 ++i) { |
| 638 if (*i == key) |
| 639 return (*delta)->extension_id; |
| 640 } |
| 641 } |
| 642 return ""; |
| 643 } |
| 644 |
| 596 void MergeOnBeforeSendHeadersResponses( | 645 void MergeOnBeforeSendHeadersResponses( |
| 597 const EventResponseDeltas& deltas, | 646 const EventResponseDeltas& deltas, |
| 598 net::HttpRequestHeaders* request_headers, | 647 net::HttpRequestHeaders* request_headers, |
| 599 std::set<std::string>* conflicting_extensions, | 648 extensions::ExtensionWarningSet* conflicting_extensions, |
| 600 const net::BoundNetLog* net_log) { | 649 const net::BoundNetLog* net_log) { |
| 601 EventResponseDeltas::const_iterator delta; | 650 EventResponseDeltas::const_iterator delta; |
| 602 | 651 |
| 603 // Here we collect which headers we have removed or set to new values | 652 // Here we collect which headers we have removed or set to new values |
| 604 // so far due to extensions of higher precedence. | 653 // so far due to extensions of higher precedence. |
| 605 std::set<std::string> removed_headers; | 654 std::set<std::string> removed_headers; |
| 606 std::set<std::string> set_headers; | 655 std::set<std::string> set_headers; |
| 607 | 656 |
| 608 // We assume here that the deltas are sorted in decreasing extension | 657 // We assume here that the deltas are sorted in decreasing extension |
| 609 // precedence (i.e. decreasing extension installation time). | 658 // precedence (i.e. decreasing extension installation time). |
| 610 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { | 659 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 611 if ((*delta)->modified_request_headers.IsEmpty() && | 660 if ((*delta)->modified_request_headers.IsEmpty() && |
| 612 (*delta)->deleted_request_headers.empty()) { | 661 (*delta)->deleted_request_headers.empty()) { |
| 613 continue; | 662 continue; |
| 614 } | 663 } |
| 615 | 664 |
| 616 // Check whether any modification affects a request header that | 665 // Check whether any modification affects a request header that |
| 617 // has been modified differently before. As deltas is sorted by decreasing | 666 // has been modified differently before. As deltas is sorted by decreasing |
| 618 // extension installation order, this takes care of precedence. | 667 // extension installation order, this takes care of precedence. |
| 619 bool extension_conflicts = false; | 668 bool extension_conflicts = false; |
| 669 std::string winning_extension_id; |
| 670 std::string conflicting_header; |
| 620 { | 671 { |
| 621 net::HttpRequestHeaders::Iterator modification( | 672 net::HttpRequestHeaders::Iterator modification( |
| 622 (*delta)->modified_request_headers); | 673 (*delta)->modified_request_headers); |
| 623 while (modification.GetNext() && !extension_conflicts) { | 674 while (modification.GetNext() && !extension_conflicts) { |
| 624 // This modification sets |key| to |value|. | 675 // This modification sets |key| to |value|. |
| 625 const std::string& key = modification.name(); | 676 const std::string& key = modification.name(); |
| 626 const std::string& value = modification.value(); | 677 const std::string& value = modification.value(); |
| 627 | 678 |
| 628 // We must not delete anything that has been modified before. | 679 // We must not delete anything that has been modified before. |
| 629 if (removed_headers.find(key) != removed_headers.end()) | 680 if (removed_headers.find(key) != removed_headers.end() && |
| 681 !extension_conflicts) { |
| 682 winning_extension_id = FindRemoveRequestHeader(deltas, key); |
| 683 conflicting_header = key; |
| 630 extension_conflicts = true; | 684 extension_conflicts = true; |
| 685 } |
| 631 | 686 |
| 632 // We must not modify anything that has been set to a *different* | 687 // We must not modify anything that has been set to a *different* |
| 633 // value before. | 688 // value before. |
| 634 if (set_headers.find(key) != set_headers.end()) { | 689 if (set_headers.find(key) != set_headers.end() && |
| 690 !extension_conflicts) { |
| 635 std::string current_value; | 691 std::string current_value; |
| 636 if (!request_headers->GetHeader(key, ¤t_value) || | 692 if (!request_headers->GetHeader(key, ¤t_value) || |
| 637 current_value != value) { | 693 current_value != value) { |
| 694 winning_extension_id = |
| 695 FindSetRequestHeader(deltas, key, current_value); |
| 696 conflicting_header = key; |
| 638 extension_conflicts = true; | 697 extension_conflicts = true; |
| 639 } | 698 } |
| 640 } | 699 } |
| 641 } | 700 } |
| 642 } | 701 } |
| 643 | 702 |
| 644 // Check whether any deletion affects a request header that has been | 703 // Check whether any deletion affects a request header that has been |
| 645 // modified before. | 704 // modified before. |
| 646 { | 705 { |
| 647 std::vector<std::string>::iterator key; | 706 std::vector<std::string>::iterator key; |
| 648 for (key = (*delta)->deleted_request_headers.begin(); | 707 for (key = (*delta)->deleted_request_headers.begin(); |
| 649 key != (*delta)->deleted_request_headers.end() && | 708 key != (*delta)->deleted_request_headers.end() && |
| 650 !extension_conflicts; | 709 !extension_conflicts; |
| 651 ++key) { | 710 ++key) { |
| 652 if (set_headers.find(*key) != set_headers.end()) | 711 if (set_headers.find(*key) != set_headers.end()) { |
| 712 std::string current_value; |
| 713 request_headers->GetHeader(*key, ¤t_value); |
| 714 winning_extension_id = |
| 715 FindSetRequestHeader(deltas, *key, current_value); |
| 716 conflicting_header = *key; |
| 653 extension_conflicts = true; | 717 extension_conflicts = true; |
| 718 } |
| 654 } | 719 } |
| 655 } | 720 } |
| 656 | 721 |
| 657 // Now execute the modifications if there were no conflicts. | 722 // Now execute the modifications if there were no conflicts. |
| 658 if (!extension_conflicts) { | 723 if (!extension_conflicts) { |
| 659 // Copy all modifications into the original headers. | 724 // Copy all modifications into the original headers. |
| 660 request_headers->MergeFrom((*delta)->modified_request_headers); | 725 request_headers->MergeFrom((*delta)->modified_request_headers); |
| 661 { | 726 { |
| 662 // Record which keys were changed. | 727 // Record which keys were changed. |
| 663 net::HttpRequestHeaders::Iterator modification( | 728 net::HttpRequestHeaders::Iterator modification( |
| 664 (*delta)->modified_request_headers); | 729 (*delta)->modified_request_headers); |
| 665 while (modification.GetNext()) | 730 while (modification.GetNext()) |
| 666 set_headers.insert(modification.name()); | 731 set_headers.insert(modification.name()); |
| 667 } | 732 } |
| 668 | 733 |
| 669 // Perform all deletions and record which keys were deleted. | 734 // Perform all deletions and record which keys were deleted. |
| 670 { | 735 { |
| 671 std::vector<std::string>::iterator key; | 736 std::vector<std::string>::iterator key; |
| 672 for (key = (*delta)->deleted_request_headers.begin(); | 737 for (key = (*delta)->deleted_request_headers.begin(); |
| 673 key != (*delta)->deleted_request_headers.end(); | 738 key != (*delta)->deleted_request_headers.end(); |
| 674 ++key) { | 739 ++key) { |
| 675 request_headers->RemoveHeader(*key); | 740 request_headers->RemoveHeader(*key); |
| 676 removed_headers.insert(*key); | 741 removed_headers.insert(*key); |
| 677 } | 742 } |
| 678 } | 743 } |
| 679 net_log->AddEvent( | 744 net_log->AddEvent( |
| 680 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, | 745 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, |
| 681 base::Bind(&NetLogModificationCallback, delta->get())); | 746 base::Bind(&NetLogModificationCallback, delta->get())); |
| 682 } else { | 747 } else { |
| 683 conflicting_extensions->insert((*delta)->extension_id); | 748 conflicting_extensions->insert( |
| 749 ExtensionWarning::CreateRequestHeaderConflictWarning( |
| 750 (*delta)->extension_id, winning_extension_id, |
| 751 conflicting_header)); |
| 684 net_log->AddEvent( | 752 net_log->AddEvent( |
| 685 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 753 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
| 686 CreateNetLogExtensionIdCallback(delta->get())); | 754 CreateNetLogExtensionIdCallback(delta->get())); |
| 687 } | 755 } |
| 688 } | 756 } |
| 689 | 757 |
| 690 MergeCookiesInOnBeforeSendHeadersResponses(deltas, request_headers, | 758 MergeCookiesInOnBeforeSendHeadersResponses(deltas, request_headers, |
| 691 conflicting_extensions, net_log); | 759 conflicting_extensions, net_log); |
| 692 } | 760 } |
| 693 | 761 |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 } | 948 } |
| 881 } | 949 } |
| 882 } | 950 } |
| 883 return modified; | 951 return modified; |
| 884 } | 952 } |
| 885 | 953 |
| 886 void MergeCookiesInOnHeadersReceivedResponses( | 954 void MergeCookiesInOnHeadersReceivedResponses( |
| 887 const EventResponseDeltas& deltas, | 955 const EventResponseDeltas& deltas, |
| 888 const net::HttpResponseHeaders* original_response_headers, | 956 const net::HttpResponseHeaders* original_response_headers, |
| 889 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, | 957 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, |
| 890 std::set<std::string>* conflicting_extensions, | 958 extensions::ExtensionWarningSet* conflicting_extensions, |
| 891 const net::BoundNetLog* net_log) { | 959 const net::BoundNetLog* net_log) { |
| 892 // Skip all work if there are no registered cookie modifications. | 960 // Skip all work if there are no registered cookie modifications. |
| 893 bool cookie_modifications_exist = false; | 961 bool cookie_modifications_exist = false; |
| 894 EventResponseDeltas::const_reverse_iterator delta; | 962 EventResponseDeltas::const_reverse_iterator delta; |
| 895 for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) { | 963 for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) { |
| 896 cookie_modifications_exist |= | 964 cookie_modifications_exist |= |
| 897 !(*delta)->response_cookie_modifications.empty(); | 965 !(*delta)->response_cookie_modifications.empty(); |
| 898 } | 966 } |
| 899 if (!cookie_modifications_exist) | 967 if (!cookie_modifications_exist) |
| 900 return; | 968 return; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 918 StoreResponseCookies(cookies, *override_response_headers); | 986 StoreResponseCookies(cookies, *override_response_headers); |
| 919 } | 987 } |
| 920 | 988 |
| 921 // Converts the key of the (key, value) pair to lower case. | 989 // Converts the key of the (key, value) pair to lower case. |
| 922 static ResponseHeader ToLowerCase(const ResponseHeader& header) { | 990 static ResponseHeader ToLowerCase(const ResponseHeader& header) { |
| 923 std::string lower_key(header.first); | 991 std::string lower_key(header.first); |
| 924 StringToLowerASCII(&lower_key); | 992 StringToLowerASCII(&lower_key); |
| 925 return ResponseHeader(lower_key, header.second); | 993 return ResponseHeader(lower_key, header.second); |
| 926 } | 994 } |
| 927 | 995 |
| 996 // Returns the extension ID of the first extension in |deltas| that removes the |
| 997 // request header identified by |key|. |
| 998 static std::string FindRemoveResponseHeader( |
| 999 const EventResponseDeltas& deltas, |
| 1000 const std::string& key) { |
| 1001 std::string lower_key = StringToLowerASCII(key); |
| 1002 EventResponseDeltas::const_iterator delta; |
| 1003 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 1004 ResponseHeaders::const_iterator i; |
| 1005 for (i = (*delta)->deleted_response_headers.begin(); |
| 1006 i != (*delta)->deleted_response_headers.end(); ++i) { |
| 1007 if (StringToLowerASCII(i->first) == lower_key) |
| 1008 return (*delta)->extension_id; |
| 1009 } |
| 1010 } |
| 1011 return ""; |
| 1012 } |
| 1013 |
| 928 void MergeOnHeadersReceivedResponses( | 1014 void MergeOnHeadersReceivedResponses( |
| 929 const EventResponseDeltas& deltas, | 1015 const EventResponseDeltas& deltas, |
| 930 const net::HttpResponseHeaders* original_response_headers, | 1016 const net::HttpResponseHeaders* original_response_headers, |
| 931 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, | 1017 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, |
| 932 std::set<std::string>* conflicting_extensions, | 1018 extensions::ExtensionWarningSet* conflicting_extensions, |
| 933 const net::BoundNetLog* net_log) { | 1019 const net::BoundNetLog* net_log) { |
| 934 EventResponseDeltas::const_iterator delta; | 1020 EventResponseDeltas::const_iterator delta; |
| 935 | 1021 |
| 936 // Here we collect which headers we have removed or added so far due to | 1022 // Here we collect which headers we have removed or added so far due to |
| 937 // extensions of higher precedence. Header keys are always stored as | 1023 // extensions of higher precedence. Header keys are always stored as |
| 938 // lower case. | 1024 // lower case. |
| 939 std::set<ResponseHeader> removed_headers; | 1025 std::set<ResponseHeader> removed_headers; |
| 940 std::set<ResponseHeader> added_headers; | 1026 std::set<ResponseHeader> added_headers; |
| 941 | 1027 |
| 942 // We assume here that the deltas are sorted in decreasing extension | 1028 // We assume here that the deltas are sorted in decreasing extension |
| 943 // precedence (i.e. decreasing extension installation time). | 1029 // precedence (i.e. decreasing extension installation time). |
| 944 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { | 1030 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 945 if ((*delta)->added_response_headers.empty() && | 1031 if ((*delta)->added_response_headers.empty() && |
| 946 (*delta)->deleted_response_headers.empty()) { | 1032 (*delta)->deleted_response_headers.empty()) { |
| 947 continue; | 1033 continue; |
| 948 } | 1034 } |
| 949 | 1035 |
| 950 // Only create a copy if we really want to modify the response headers. | 1036 // Only create a copy if we really want to modify the response headers. |
| 951 if (override_response_headers->get() == NULL) { | 1037 if (override_response_headers->get() == NULL) { |
| 952 *override_response_headers = new net::HttpResponseHeaders( | 1038 *override_response_headers = new net::HttpResponseHeaders( |
| 953 original_response_headers->raw_headers()); | 1039 original_response_headers->raw_headers()); |
| 954 } | 1040 } |
| 955 | 1041 |
| 956 // We consider modifications as pairs of (delete, add) operations. | 1042 // We consider modifications as pairs of (delete, add) operations. |
| 957 // If a header is deleted twice by different extensions we assume that the | 1043 // If a header is deleted twice by different extensions we assume that the |
| 958 // intention was to modify it to different values and consider this a | 1044 // intention was to modify it to different values and consider this a |
| 959 // conflict. As deltas is sorted by decreasing extension installation order, | 1045 // conflict. As deltas is sorted by decreasing extension installation order, |
| 960 // this takes care of precedence. | 1046 // this takes care of precedence. |
| 961 bool extension_conflicts = false; | 1047 bool extension_conflicts = false; |
| 1048 std::string conflicting_header; |
| 1049 std::string winning_extension_id; |
| 962 ResponseHeaders::const_iterator i; | 1050 ResponseHeaders::const_iterator i; |
| 963 for (i = (*delta)->deleted_response_headers.begin(); | 1051 for (i = (*delta)->deleted_response_headers.begin(); |
| 964 i != (*delta)->deleted_response_headers.end(); ++i) { | 1052 i != (*delta)->deleted_response_headers.end(); ++i) { |
| 965 if (removed_headers.find(ToLowerCase(*i)) != removed_headers.end()) { | 1053 if (removed_headers.find(ToLowerCase(*i)) != removed_headers.end()) { |
| 1054 winning_extension_id = FindRemoveResponseHeader(deltas, i->first); |
| 1055 conflicting_header = i->first; |
| 966 extension_conflicts = true; | 1056 extension_conflicts = true; |
| 967 break; | 1057 break; |
| 968 } | 1058 } |
| 969 } | 1059 } |
| 970 | 1060 |
| 971 // Now execute the modifications if there were no conflicts. | 1061 // Now execute the modifications if there were no conflicts. |
| 972 if (!extension_conflicts) { | 1062 if (!extension_conflicts) { |
| 973 // Delete headers | 1063 // Delete headers |
| 974 { | 1064 { |
| 975 for (i = (*delta)->deleted_response_headers.begin(); | 1065 for (i = (*delta)->deleted_response_headers.begin(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 987 if (added_headers.find(lowercase_header) != added_headers.end()) | 1077 if (added_headers.find(lowercase_header) != added_headers.end()) |
| 988 continue; | 1078 continue; |
| 989 added_headers.insert(lowercase_header); | 1079 added_headers.insert(lowercase_header); |
| 990 (*override_response_headers)->AddHeader(i->first + ": " + i->second); | 1080 (*override_response_headers)->AddHeader(i->first + ": " + i->second); |
| 991 } | 1081 } |
| 992 } | 1082 } |
| 993 net_log->AddEvent( | 1083 net_log->AddEvent( |
| 994 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, | 1084 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, |
| 995 CreateNetLogExtensionIdCallback(delta->get())); | 1085 CreateNetLogExtensionIdCallback(delta->get())); |
| 996 } else { | 1086 } else { |
| 997 conflicting_extensions->insert((*delta)->extension_id); | 1087 conflicting_extensions->insert( |
| 1088 ExtensionWarning::CreateResponseHeaderConflictWarning( |
| 1089 (*delta)->extension_id, winning_extension_id, |
| 1090 conflicting_header)); |
| 998 net_log->AddEvent( | 1091 net_log->AddEvent( |
| 999 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 1092 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
| 1000 CreateNetLogExtensionIdCallback(delta->get())); | 1093 CreateNetLogExtensionIdCallback(delta->get())); |
| 1001 } | 1094 } |
| 1002 } | 1095 } |
| 1003 | 1096 |
| 1004 MergeCookiesInOnHeadersReceivedResponses(deltas, original_response_headers, | 1097 MergeCookiesInOnHeadersReceivedResponses(deltas, original_response_headers, |
| 1005 override_response_headers, conflicting_extensions, net_log); | 1098 override_response_headers, conflicting_extensions, net_log); |
| 1006 } | 1099 } |
| 1007 | 1100 |
| 1008 bool MergeOnAuthRequiredResponses( | 1101 bool MergeOnAuthRequiredResponses( |
| 1009 const EventResponseDeltas& deltas, | 1102 const EventResponseDeltas& deltas, |
| 1010 net::AuthCredentials* auth_credentials, | 1103 net::AuthCredentials* auth_credentials, |
| 1011 std::set<std::string>* conflicting_extensions, | 1104 extensions::ExtensionWarningSet* conflicting_extensions, |
| 1012 const net::BoundNetLog* net_log) { | 1105 const net::BoundNetLog* net_log) { |
| 1013 CHECK(auth_credentials); | 1106 CHECK(auth_credentials); |
| 1014 bool credentials_set = false; | 1107 bool credentials_set = false; |
| 1108 std::string winning_extension_id; |
| 1015 | 1109 |
| 1016 for (EventResponseDeltas::const_iterator delta = deltas.begin(); | 1110 for (EventResponseDeltas::const_iterator delta = deltas.begin(); |
| 1017 delta != deltas.end(); | 1111 delta != deltas.end(); |
| 1018 ++delta) { | 1112 ++delta) { |
| 1019 if (!(*delta)->auth_credentials.get()) | 1113 if (!(*delta)->auth_credentials.get()) |
| 1020 continue; | 1114 continue; |
| 1021 bool different = | 1115 bool different = |
| 1022 auth_credentials->username() != | 1116 auth_credentials->username() != |
| 1023 (*delta)->auth_credentials->username() || | 1117 (*delta)->auth_credentials->username() || |
| 1024 auth_credentials->password() != (*delta)->auth_credentials->password(); | 1118 auth_credentials->password() != (*delta)->auth_credentials->password(); |
| 1025 if (credentials_set && different) { | 1119 if (credentials_set && different) { |
| 1026 conflicting_extensions->insert((*delta)->extension_id); | 1120 conflicting_extensions->insert( |
| 1121 ExtensionWarning::CreateCredentialsConflictWarning( |
| 1122 (*delta)->extension_id, winning_extension_id)); |
| 1027 net_log->AddEvent( | 1123 net_log->AddEvent( |
| 1028 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 1124 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
| 1029 CreateNetLogExtensionIdCallback(delta->get())); | 1125 CreateNetLogExtensionIdCallback(delta->get())); |
| 1030 } else { | 1126 } else { |
| 1031 net_log->AddEvent( | 1127 net_log->AddEvent( |
| 1032 net::NetLog::TYPE_CHROME_EXTENSION_PROVIDE_AUTH_CREDENTIALS, | 1128 net::NetLog::TYPE_CHROME_EXTENSION_PROVIDE_AUTH_CREDENTIALS, |
| 1033 CreateNetLogExtensionIdCallback(delta->get())); | 1129 CreateNetLogExtensionIdCallback(delta->get())); |
| 1034 *auth_credentials = *(*delta)->auth_credentials; | 1130 *auth_credentials = *(*delta)->auth_credentials; |
| 1035 credentials_set = true; | 1131 credentials_set = true; |
| 1132 winning_extension_id = (*delta)->extension_id; |
| 1036 } | 1133 } |
| 1037 } | 1134 } |
| 1038 return credentials_set; | 1135 return credentials_set; |
| 1039 } | 1136 } |
| 1040 | 1137 |
| 1041 | 1138 |
| 1042 #define ARRAYEND(array) (array + arraysize(array)) | 1139 #define ARRAYEND(array) (array + arraysize(array)) |
| 1043 | 1140 |
| 1044 bool IsRelevantResourceType(ResourceType::Type type) { | 1141 bool IsRelevantResourceType(ResourceType::Type type) { |
| 1045 ResourceType::Type* iter = | 1142 ResourceType::Type* iter = |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1069 void ClearCacheOnNavigation() { | 1166 void ClearCacheOnNavigation() { |
| 1070 if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { | 1167 if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { |
| 1071 ClearCacheOnNavigationOnUI(); | 1168 ClearCacheOnNavigationOnUI(); |
| 1072 } else { | 1169 } else { |
| 1073 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 1170 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| 1074 base::Bind(&ClearCacheOnNavigationOnUI)); | 1171 base::Bind(&ClearCacheOnNavigationOnUI)); |
| 1075 } | 1172 } |
| 1076 } | 1173 } |
| 1077 | 1174 |
| 1078 } // namespace extension_web_request_api_helpers | 1175 } // namespace extension_web_request_api_helpers |
| OLD | NEW |