| 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_number_conversions.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| 11 #include "base/values.h" | 11 #include "base/values.h" |
| 12 #include "chrome/browser/extensions/api/web_request/web_request_api.h" | 12 #include "chrome/browser/extensions/api/web_request/web_request_api.h" |
| 13 #include "chrome/browser/extensions/extension_warning_set.h" |
| 13 #include "chrome/browser/renderer_host/web_cache_manager.h" | 14 #include "chrome/browser/renderer_host/web_cache_manager.h" |
| 14 #include "chrome/common/url_constants.h" | 15 #include "chrome/common/url_constants.h" |
| 15 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
| 16 #include "net/base/net_log.h" | 17 #include "net/base/net_log.h" |
| 17 #include "net/cookies/parsed_cookie.h" | 18 #include "net/cookies/parsed_cookie.h" |
| 18 #include "net/http/http_util.h" | 19 #include "net/http/http_util.h" |
| 19 #include "net/url_request/url_request.h" | 20 #include "net/url_request/url_request.h" |
| 20 | 21 |
| 22 // TODO(battre): move all static functions into an anonymous namespace at the |
| 23 // top of this file. |
| 24 |
| 25 using extensions::ExtensionWarning; |
| 26 |
| 21 namespace extension_web_request_api_helpers { | 27 namespace extension_web_request_api_helpers { |
| 22 | 28 |
| 23 namespace { | 29 namespace { |
| 24 | 30 |
| 25 // A ParsedRequestCookie consists of the key and value of the cookie. | 31 // A ParsedRequestCookie consists of the key and value of the cookie. |
| 26 typedef std::pair<base::StringPiece, base::StringPiece> ParsedRequestCookie; | 32 typedef std::pair<base::StringPiece, base::StringPiece> ParsedRequestCookie; |
| 27 typedef std::vector<ParsedRequestCookie> ParsedRequestCookies; | 33 typedef std::vector<ParsedRequestCookie> ParsedRequestCookies; |
| 28 typedef std::vector<linked_ptr<net::ParsedCookie> > ParsedResponseCookies; | 34 typedef std::vector<linked_ptr<net::ParsedCookie> > ParsedResponseCookies; |
| 29 | 35 |
| 30 static const char* kResourceTypeStrings[] = { | 36 static const char* kResourceTypeStrings[] = { |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 // Helper function for MergeOnBeforeRequestResponses() that allows ignoring | 297 // Helper function for MergeOnBeforeRequestResponses() that allows ignoring |
| 292 // all redirects but those to data:// urls and about:blank. This is important | 298 // all redirects but those to data:// urls and about:blank. This is important |
| 293 // to treat these URLs as "cancel urls", i.e. URLs that extensions redirect | 299 // to treat these URLs as "cancel urls", i.e. URLs that extensions redirect |
| 294 // to if they want to express that they want to cancel a request. This reduces | 300 // to if they want to express that they want to cancel a request. This reduces |
| 295 // the number of conflicts that we need to flag, as canceling is considered | 301 // the number of conflicts that we need to flag, as canceling is considered |
| 296 // a higher precedence operation that redirects. | 302 // a higher precedence operation that redirects. |
| 297 // Returns whether a redirect occurred. | 303 // Returns whether a redirect occurred. |
| 298 static bool MergeOnBeforeRequestResponsesHelper( | 304 static bool MergeOnBeforeRequestResponsesHelper( |
| 299 const EventResponseDeltas& deltas, | 305 const EventResponseDeltas& deltas, |
| 300 GURL* new_url, | 306 GURL* new_url, |
| 301 std::set<std::string>* conflicting_extensions, | 307 extensions::ExtensionWarningSet* conflicting_extensions, |
| 302 const net::BoundNetLog* net_log, | 308 const net::BoundNetLog* net_log, |
| 303 bool consider_only_cancel_scheme_urls) { | 309 bool consider_only_cancel_scheme_urls) { |
| 304 bool redirected = false; | 310 bool redirected = false; |
| 305 | 311 |
| 312 // Extension that determines the |new_url|. |
| 313 std::string winning_extension_id; |
| 306 EventResponseDeltas::const_iterator delta; | 314 EventResponseDeltas::const_iterator delta; |
| 307 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { | 315 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 308 if ((*delta)->new_url.is_empty()) | 316 if ((*delta)->new_url.is_empty()) |
| 309 continue; | 317 continue; |
| 310 if (consider_only_cancel_scheme_urls && | 318 if (consider_only_cancel_scheme_urls && |
| 311 !(*delta)->new_url.SchemeIs(chrome::kDataScheme) && | 319 !(*delta)->new_url.SchemeIs(chrome::kDataScheme) && |
| 312 (*delta)->new_url.spec() != "about:blank") { | 320 (*delta)->new_url.spec() != "about:blank") { |
| 313 continue; | 321 continue; |
| 314 } | 322 } |
| 315 | 323 |
| 316 if (!redirected || *new_url == (*delta)->new_url) { | 324 if (!redirected || *new_url == (*delta)->new_url) { |
| 317 *new_url = (*delta)->new_url; | 325 *new_url = (*delta)->new_url; |
| 326 winning_extension_id = (*delta)->extension_id; |
| 318 redirected = true; | 327 redirected = true; |
| 319 net_log->AddEvent( | 328 net_log->AddEvent( |
| 320 net::NetLog::TYPE_CHROME_EXTENSION_REDIRECTED_REQUEST, | 329 net::NetLog::TYPE_CHROME_EXTENSION_REDIRECTED_REQUEST, |
| 321 CreateNetLogExtensionIdCallback(delta->get())); | 330 CreateNetLogExtensionIdCallback(delta->get())); |
| 322 } else { | 331 } else { |
| 323 conflicting_extensions->insert((*delta)->extension_id); | 332 conflicting_extensions->insert( |
| 333 ExtensionWarning::CreateRedirectConflictWarning( |
| 334 (*delta)->extension_id, |
| 335 winning_extension_id, |
| 336 (*delta)->new_url, |
| 337 *new_url)); |
| 324 net_log->AddEvent( | 338 net_log->AddEvent( |
| 325 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 339 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
| 326 CreateNetLogExtensionIdCallback(delta->get())); | 340 CreateNetLogExtensionIdCallback(delta->get())); |
| 327 } | 341 } |
| 328 } | 342 } |
| 329 return redirected; | 343 return redirected; |
| 330 } | 344 } |
| 331 | 345 |
| 332 void MergeOnBeforeRequestResponses( | 346 void MergeOnBeforeRequestResponses( |
| 333 const EventResponseDeltas& deltas, | 347 const EventResponseDeltas& deltas, |
| 334 GURL* new_url, | 348 GURL* new_url, |
| 335 std::set<std::string>* conflicting_extensions, | 349 extensions::ExtensionWarningSet* conflicting_extensions, |
| 336 const net::BoundNetLog* net_log) { | 350 const net::BoundNetLog* net_log) { |
| 337 | 351 |
| 338 // First handle only redirects to data:// URLs and about:blank. These are a | 352 // First handle only redirects to data:// URLs and about:blank. These are a |
| 339 // special case as they represent a way of cancelling a request. | 353 // special case as they represent a way of cancelling a request. |
| 340 if (MergeOnBeforeRequestResponsesHelper( | 354 if (MergeOnBeforeRequestResponsesHelper( |
| 341 deltas, new_url, conflicting_extensions, net_log, true)) { | 355 deltas, new_url, conflicting_extensions, net_log, true)) { |
| 342 // If any extension cancelled a request by redirecting to a data:// URL or | 356 // If any extension cancelled a request by redirecting to a data:// URL or |
| 343 // about:blank, we don't consider the other redirects. | 357 // about:blank, we don't consider the other redirects. |
| 344 return; | 358 return; |
| 345 } | 359 } |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 } | 537 } |
| 524 } | 538 } |
| 525 } | 539 } |
| 526 } | 540 } |
| 527 return modified; | 541 return modified; |
| 528 } | 542 } |
| 529 | 543 |
| 530 void MergeCookiesInOnBeforeSendHeadersResponses( | 544 void MergeCookiesInOnBeforeSendHeadersResponses( |
| 531 const EventResponseDeltas& deltas, | 545 const EventResponseDeltas& deltas, |
| 532 net::HttpRequestHeaders* request_headers, | 546 net::HttpRequestHeaders* request_headers, |
| 533 std::set<std::string>* conflicting_extensions, | 547 extensions::ExtensionWarningSet* conflicting_extensions, |
| 534 const net::BoundNetLog* net_log) { | 548 const net::BoundNetLog* net_log) { |
| 535 // Skip all work if there are no registered cookie modifications. | 549 // Skip all work if there are no registered cookie modifications. |
| 536 bool cookie_modifications_exist = false; | 550 bool cookie_modifications_exist = false; |
| 537 EventResponseDeltas::const_iterator delta; | 551 EventResponseDeltas::const_iterator delta; |
| 538 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { | 552 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 539 cookie_modifications_exist |= | 553 cookie_modifications_exist |= |
| 540 !(*delta)->request_cookie_modifications.empty(); | 554 !(*delta)->request_cookie_modifications.empty(); |
| 541 } | 555 } |
| 542 if (!cookie_modifications_exist) | 556 if (!cookie_modifications_exist) |
| 543 return; | 557 return; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 555 modified |= MergeRemoveRequestCookieModifications(deltas, &cookies); | 569 modified |= MergeRemoveRequestCookieModifications(deltas, &cookies); |
| 556 | 570 |
| 557 // Reassemble and store new cookie line. | 571 // Reassemble and store new cookie line. |
| 558 if (modified) { | 572 if (modified) { |
| 559 std::string new_cookie_header = SerializeRequestCookieLine(cookies); | 573 std::string new_cookie_header = SerializeRequestCookieLine(cookies); |
| 560 request_headers->SetHeader(net::HttpRequestHeaders::kCookie, | 574 request_headers->SetHeader(net::HttpRequestHeaders::kCookie, |
| 561 new_cookie_header); | 575 new_cookie_header); |
| 562 } | 576 } |
| 563 } | 577 } |
| 564 | 578 |
| 579 // Returns the extension ID of the first extension in |deltas| that sets the |
| 580 // request header identified by |key| to |value|. |
| 581 static std::string FindSetRequestHeader( |
| 582 const EventResponseDeltas& deltas, |
| 583 const std::string& key, |
| 584 const std::string& value) { |
| 585 EventResponseDeltas::const_iterator delta; |
| 586 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 587 net::HttpRequestHeaders::Iterator modification( |
| 588 (*delta)->modified_request_headers); |
| 589 while (modification.GetNext()) { |
| 590 if (key == modification.name() && value == modification.value()) |
| 591 return (*delta)->extension_id; |
| 592 } |
| 593 } |
| 594 return ""; |
| 595 } |
| 596 |
| 597 // Returns the extension ID of the first extension in |deltas| that removes the |
| 598 // request header identified by |key|. |
| 599 static std::string FindRemoveRequestHeader( |
| 600 const EventResponseDeltas& deltas, |
| 601 const std::string& key) { |
| 602 EventResponseDeltas::const_iterator delta; |
| 603 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 604 std::vector<std::string>::iterator i; |
| 605 for (i = (*delta)->deleted_request_headers.begin(); |
| 606 i != (*delta)->deleted_request_headers.end(); |
| 607 ++i) { |
| 608 if (*i == key) |
| 609 return (*delta)->extension_id; |
| 610 } |
| 611 } |
| 612 return ""; |
| 613 } |
| 614 |
| 565 void MergeOnBeforeSendHeadersResponses( | 615 void MergeOnBeforeSendHeadersResponses( |
| 566 const EventResponseDeltas& deltas, | 616 const EventResponseDeltas& deltas, |
| 567 net::HttpRequestHeaders* request_headers, | 617 net::HttpRequestHeaders* request_headers, |
| 568 std::set<std::string>* conflicting_extensions, | 618 extensions::ExtensionWarningSet* conflicting_extensions, |
| 569 const net::BoundNetLog* net_log) { | 619 const net::BoundNetLog* net_log) { |
| 570 EventResponseDeltas::const_iterator delta; | 620 EventResponseDeltas::const_iterator delta; |
| 571 | 621 |
| 572 // Here we collect which headers we have removed or set to new values | 622 // Here we collect which headers we have removed or set to new values |
| 573 // so far due to extensions of higher precedence. | 623 // so far due to extensions of higher precedence. |
| 574 std::set<std::string> removed_headers; | 624 std::set<std::string> removed_headers; |
| 575 std::set<std::string> set_headers; | 625 std::set<std::string> set_headers; |
| 576 | 626 |
| 577 // We assume here that the deltas are sorted in decreasing extension | 627 // We assume here that the deltas are sorted in decreasing extension |
| 578 // precedence (i.e. decreasing extension installation time). | 628 // precedence (i.e. decreasing extension installation time). |
| 579 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { | 629 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 580 if ((*delta)->modified_request_headers.IsEmpty() && | 630 if ((*delta)->modified_request_headers.IsEmpty() && |
| 581 (*delta)->deleted_request_headers.empty()) { | 631 (*delta)->deleted_request_headers.empty()) { |
| 582 continue; | 632 continue; |
| 583 } | 633 } |
| 584 | 634 |
| 585 // Check whether any modification affects a request header that | 635 // Check whether any modification affects a request header that |
| 586 // has been modified differently before. As deltas is sorted by decreasing | 636 // has been modified differently before. As deltas is sorted by decreasing |
| 587 // extension installation order, this takes care of precedence. | 637 // extension installation order, this takes care of precedence. |
| 588 bool extension_conflicts = false; | 638 bool extension_conflicts = false; |
| 639 std::string winning_extension_id; |
| 640 std::string conflicting_header; |
| 589 { | 641 { |
| 590 net::HttpRequestHeaders::Iterator modification( | 642 net::HttpRequestHeaders::Iterator modification( |
| 591 (*delta)->modified_request_headers); | 643 (*delta)->modified_request_headers); |
| 592 while (modification.GetNext() && !extension_conflicts) { | 644 while (modification.GetNext() && !extension_conflicts) { |
| 593 // This modification sets |key| to |value|. | 645 // This modification sets |key| to |value|. |
| 594 const std::string& key = modification.name(); | 646 const std::string& key = modification.name(); |
| 595 const std::string& value = modification.value(); | 647 const std::string& value = modification.value(); |
| 596 | 648 |
| 597 // We must not delete anything that has been modified before. | 649 // We must not delete anything that has been modified before. |
| 598 if (removed_headers.find(key) != removed_headers.end()) | 650 if (removed_headers.find(key) != removed_headers.end() && |
| 651 !extension_conflicts) { |
| 652 winning_extension_id = FindRemoveRequestHeader(deltas, key); |
| 653 conflicting_header = key; |
| 599 extension_conflicts = true; | 654 extension_conflicts = true; |
| 655 } |
| 600 | 656 |
| 601 // We must not modify anything that has been set to a *different* | 657 // We must not modify anything that has been set to a *different* |
| 602 // value before. | 658 // value before. |
| 603 if (set_headers.find(key) != set_headers.end()) { | 659 if (set_headers.find(key) != set_headers.end() && |
| 660 !extension_conflicts) { |
| 604 std::string current_value; | 661 std::string current_value; |
| 605 if (!request_headers->GetHeader(key, ¤t_value) || | 662 if (!request_headers->GetHeader(key, ¤t_value) || |
| 606 current_value != value) { | 663 current_value != value) { |
| 664 winning_extension_id = |
| 665 FindSetRequestHeader(deltas, key, current_value); |
| 666 conflicting_header = key; |
| 607 extension_conflicts = true; | 667 extension_conflicts = true; |
| 608 } | 668 } |
| 609 } | 669 } |
| 610 } | 670 } |
| 611 } | 671 } |
| 612 | 672 |
| 613 // Check whether any deletion affects a request header that has been | 673 // Check whether any deletion affects a request header that has been |
| 614 // modified before. | 674 // modified before. |
| 615 { | 675 { |
| 616 std::vector<std::string>::iterator key; | 676 std::vector<std::string>::iterator key; |
| 617 for (key = (*delta)->deleted_request_headers.begin(); | 677 for (key = (*delta)->deleted_request_headers.begin(); |
| 618 key != (*delta)->deleted_request_headers.end() && | 678 key != (*delta)->deleted_request_headers.end() && |
| 619 !extension_conflicts; | 679 !extension_conflicts; |
| 620 ++key) { | 680 ++key) { |
| 621 if (set_headers.find(*key) != set_headers.end()) | 681 if (set_headers.find(*key) != set_headers.end()) { |
| 682 std::string current_value; |
| 683 request_headers->GetHeader(*key, ¤t_value); |
| 684 winning_extension_id = |
| 685 FindSetRequestHeader(deltas, *key, current_value); |
| 686 conflicting_header = *key; |
| 622 extension_conflicts = true; | 687 extension_conflicts = true; |
| 688 } |
| 623 } | 689 } |
| 624 } | 690 } |
| 625 | 691 |
| 626 // Now execute the modifications if there were no conflicts. | 692 // Now execute the modifications if there were no conflicts. |
| 627 if (!extension_conflicts) { | 693 if (!extension_conflicts) { |
| 628 // Copy all modifications into the original headers. | 694 // Copy all modifications into the original headers. |
| 629 request_headers->MergeFrom((*delta)->modified_request_headers); | 695 request_headers->MergeFrom((*delta)->modified_request_headers); |
| 630 { | 696 { |
| 631 // Record which keys were changed. | 697 // Record which keys were changed. |
| 632 net::HttpRequestHeaders::Iterator modification( | 698 net::HttpRequestHeaders::Iterator modification( |
| 633 (*delta)->modified_request_headers); | 699 (*delta)->modified_request_headers); |
| 634 while (modification.GetNext()) | 700 while (modification.GetNext()) |
| 635 set_headers.insert(modification.name()); | 701 set_headers.insert(modification.name()); |
| 636 } | 702 } |
| 637 | 703 |
| 638 // Perform all deletions and record which keys were deleted. | 704 // Perform all deletions and record which keys were deleted. |
| 639 { | 705 { |
| 640 std::vector<std::string>::iterator key; | 706 std::vector<std::string>::iterator key; |
| 641 for (key = (*delta)->deleted_request_headers.begin(); | 707 for (key = (*delta)->deleted_request_headers.begin(); |
| 642 key != (*delta)->deleted_request_headers.end(); | 708 key != (*delta)->deleted_request_headers.end(); |
| 643 ++key) { | 709 ++key) { |
| 644 request_headers->RemoveHeader(*key); | 710 request_headers->RemoveHeader(*key); |
| 645 removed_headers.insert(*key); | 711 removed_headers.insert(*key); |
| 646 } | 712 } |
| 647 } | 713 } |
| 648 net_log->AddEvent( | 714 net_log->AddEvent( |
| 649 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, | 715 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, |
| 650 base::Bind(&NetLogModificationCallback, delta->get())); | 716 base::Bind(&NetLogModificationCallback, delta->get())); |
| 651 } else { | 717 } else { |
| 652 conflicting_extensions->insert((*delta)->extension_id); | 718 conflicting_extensions->insert( |
| 719 ExtensionWarning::CreateRequestHeaderConflictWarning( |
| 720 (*delta)->extension_id, winning_extension_id, |
| 721 conflicting_header)); |
| 653 net_log->AddEvent( | 722 net_log->AddEvent( |
| 654 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 723 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
| 655 CreateNetLogExtensionIdCallback(delta->get())); | 724 CreateNetLogExtensionIdCallback(delta->get())); |
| 656 } | 725 } |
| 657 } | 726 } |
| 658 | 727 |
| 659 MergeCookiesInOnBeforeSendHeadersResponses(deltas, request_headers, | 728 MergeCookiesInOnBeforeSendHeadersResponses(deltas, request_headers, |
| 660 conflicting_extensions, net_log); | 729 conflicting_extensions, net_log); |
| 661 } | 730 } |
| 662 | 731 |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 } | 898 } |
| 830 } | 899 } |
| 831 } | 900 } |
| 832 return modified; | 901 return modified; |
| 833 } | 902 } |
| 834 | 903 |
| 835 void MergeCookiesInOnHeadersReceivedResponses( | 904 void MergeCookiesInOnHeadersReceivedResponses( |
| 836 const EventResponseDeltas& deltas, | 905 const EventResponseDeltas& deltas, |
| 837 const net::HttpResponseHeaders* original_response_headers, | 906 const net::HttpResponseHeaders* original_response_headers, |
| 838 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, | 907 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, |
| 839 std::set<std::string>* conflicting_extensions, | 908 extensions::ExtensionWarningSet* conflicting_extensions, |
| 840 const net::BoundNetLog* net_log) { | 909 const net::BoundNetLog* net_log) { |
| 841 // Skip all work if there are no registered cookie modifications. | 910 // Skip all work if there are no registered cookie modifications. |
| 842 bool cookie_modifications_exist = false; | 911 bool cookie_modifications_exist = false; |
| 843 EventResponseDeltas::const_reverse_iterator delta; | 912 EventResponseDeltas::const_reverse_iterator delta; |
| 844 for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) { | 913 for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) { |
| 845 cookie_modifications_exist |= | 914 cookie_modifications_exist |= |
| 846 !(*delta)->response_cookie_modifications.empty(); | 915 !(*delta)->response_cookie_modifications.empty(); |
| 847 } | 916 } |
| 848 if (!cookie_modifications_exist) | 917 if (!cookie_modifications_exist) |
| 849 return; | 918 return; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 867 StoreResponseCookies(cookies, *override_response_headers); | 936 StoreResponseCookies(cookies, *override_response_headers); |
| 868 } | 937 } |
| 869 | 938 |
| 870 // Converts the key of the (key, value) pair to lower case. | 939 // Converts the key of the (key, value) pair to lower case. |
| 871 static ResponseHeader ToLowerCase(const ResponseHeader& header) { | 940 static ResponseHeader ToLowerCase(const ResponseHeader& header) { |
| 872 std::string lower_key(header.first); | 941 std::string lower_key(header.first); |
| 873 StringToLowerASCII(&lower_key); | 942 StringToLowerASCII(&lower_key); |
| 874 return ResponseHeader(lower_key, header.second); | 943 return ResponseHeader(lower_key, header.second); |
| 875 } | 944 } |
| 876 | 945 |
| 946 // Returns the extension ID of the first extension in |deltas| that removes the |
| 947 // request header identified by |key|. |
| 948 static std::string FindRemoveResponseHeader( |
| 949 const EventResponseDeltas& deltas, |
| 950 const std::string& key) { |
| 951 std::string lower_key = StringToLowerASCII(key); |
| 952 EventResponseDeltas::const_iterator delta; |
| 953 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 954 ResponseHeaders::const_iterator i; |
| 955 for (i = (*delta)->deleted_response_headers.begin(); |
| 956 i != (*delta)->deleted_response_headers.end(); ++i) { |
| 957 if (StringToLowerASCII(i->first) == lower_key) |
| 958 return (*delta)->extension_id; |
| 959 } |
| 960 } |
| 961 return ""; |
| 962 } |
| 963 |
| 877 void MergeOnHeadersReceivedResponses( | 964 void MergeOnHeadersReceivedResponses( |
| 878 const EventResponseDeltas& deltas, | 965 const EventResponseDeltas& deltas, |
| 879 const net::HttpResponseHeaders* original_response_headers, | 966 const net::HttpResponseHeaders* original_response_headers, |
| 880 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, | 967 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, |
| 881 std::set<std::string>* conflicting_extensions, | 968 extensions::ExtensionWarningSet* conflicting_extensions, |
| 882 const net::BoundNetLog* net_log) { | 969 const net::BoundNetLog* net_log) { |
| 883 EventResponseDeltas::const_iterator delta; | 970 EventResponseDeltas::const_iterator delta; |
| 884 | 971 |
| 885 // Here we collect which headers we have removed or added so far due to | 972 // Here we collect which headers we have removed or added so far due to |
| 886 // extensions of higher precedence. Header keys are always stored as | 973 // extensions of higher precedence. Header keys are always stored as |
| 887 // lower case. | 974 // lower case. |
| 888 std::set<ResponseHeader> removed_headers; | 975 std::set<ResponseHeader> removed_headers; |
| 889 std::set<ResponseHeader> added_headers; | 976 std::set<ResponseHeader> added_headers; |
| 890 | 977 |
| 891 // We assume here that the deltas are sorted in decreasing extension | 978 // We assume here that the deltas are sorted in decreasing extension |
| 892 // precedence (i.e. decreasing extension installation time). | 979 // precedence (i.e. decreasing extension installation time). |
| 893 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { | 980 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { |
| 894 if ((*delta)->added_response_headers.empty() && | 981 if ((*delta)->added_response_headers.empty() && |
| 895 (*delta)->deleted_response_headers.empty()) { | 982 (*delta)->deleted_response_headers.empty()) { |
| 896 continue; | 983 continue; |
| 897 } | 984 } |
| 898 | 985 |
| 899 // Only create a copy if we really want to modify the response headers. | 986 // Only create a copy if we really want to modify the response headers. |
| 900 if (override_response_headers->get() == NULL) { | 987 if (override_response_headers->get() == NULL) { |
| 901 *override_response_headers = new net::HttpResponseHeaders( | 988 *override_response_headers = new net::HttpResponseHeaders( |
| 902 original_response_headers->raw_headers()); | 989 original_response_headers->raw_headers()); |
| 903 } | 990 } |
| 904 | 991 |
| 905 // We consider modifications as pairs of (delete, add) operations. | 992 // We consider modifications as pairs of (delete, add) operations. |
| 906 // If a header is deleted twice by different extensions we assume that the | 993 // If a header is deleted twice by different extensions we assume that the |
| 907 // intention was to modify it to different values and consider this a | 994 // intention was to modify it to different values and consider this a |
| 908 // conflict. As deltas is sorted by decreasing extension installation order, | 995 // conflict. As deltas is sorted by decreasing extension installation order, |
| 909 // this takes care of precedence. | 996 // this takes care of precedence. |
| 910 bool extension_conflicts = false; | 997 bool extension_conflicts = false; |
| 998 std::string conflicting_header; |
| 999 std::string winning_extension_id; |
| 911 ResponseHeaders::const_iterator i; | 1000 ResponseHeaders::const_iterator i; |
| 912 for (i = (*delta)->deleted_response_headers.begin(); | 1001 for (i = (*delta)->deleted_response_headers.begin(); |
| 913 i != (*delta)->deleted_response_headers.end(); ++i) { | 1002 i != (*delta)->deleted_response_headers.end(); ++i) { |
| 914 if (removed_headers.find(ToLowerCase(*i)) != removed_headers.end()) { | 1003 if (removed_headers.find(ToLowerCase(*i)) != removed_headers.end()) { |
| 1004 winning_extension_id = FindRemoveResponseHeader(deltas, i->first); |
| 1005 conflicting_header = i->first; |
| 915 extension_conflicts = true; | 1006 extension_conflicts = true; |
| 916 break; | 1007 break; |
| 917 } | 1008 } |
| 918 } | 1009 } |
| 919 | 1010 |
| 920 // Now execute the modifications if there were no conflicts. | 1011 // Now execute the modifications if there were no conflicts. |
| 921 if (!extension_conflicts) { | 1012 if (!extension_conflicts) { |
| 922 // Delete headers | 1013 // Delete headers |
| 923 { | 1014 { |
| 924 for (i = (*delta)->deleted_response_headers.begin(); | 1015 for (i = (*delta)->deleted_response_headers.begin(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 936 if (added_headers.find(lowercase_header) != added_headers.end()) | 1027 if (added_headers.find(lowercase_header) != added_headers.end()) |
| 937 continue; | 1028 continue; |
| 938 added_headers.insert(lowercase_header); | 1029 added_headers.insert(lowercase_header); |
| 939 (*override_response_headers)->AddHeader(i->first + ": " + i->second); | 1030 (*override_response_headers)->AddHeader(i->first + ": " + i->second); |
| 940 } | 1031 } |
| 941 } | 1032 } |
| 942 net_log->AddEvent( | 1033 net_log->AddEvent( |
| 943 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, | 1034 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, |
| 944 CreateNetLogExtensionIdCallback(delta->get())); | 1035 CreateNetLogExtensionIdCallback(delta->get())); |
| 945 } else { | 1036 } else { |
| 946 conflicting_extensions->insert((*delta)->extension_id); | 1037 conflicting_extensions->insert( |
| 1038 ExtensionWarning::CreateResponseHeaderConflictWarning( |
| 1039 (*delta)->extension_id, winning_extension_id, |
| 1040 conflicting_header)); |
| 947 net_log->AddEvent( | 1041 net_log->AddEvent( |
| 948 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 1042 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
| 949 CreateNetLogExtensionIdCallback(delta->get())); | 1043 CreateNetLogExtensionIdCallback(delta->get())); |
| 950 } | 1044 } |
| 951 } | 1045 } |
| 952 | 1046 |
| 953 MergeCookiesInOnHeadersReceivedResponses(deltas, original_response_headers, | 1047 MergeCookiesInOnHeadersReceivedResponses(deltas, original_response_headers, |
| 954 override_response_headers, conflicting_extensions, net_log); | 1048 override_response_headers, conflicting_extensions, net_log); |
| 955 } | 1049 } |
| 956 | 1050 |
| 957 bool MergeOnAuthRequiredResponses( | 1051 bool MergeOnAuthRequiredResponses( |
| 958 const EventResponseDeltas& deltas, | 1052 const EventResponseDeltas& deltas, |
| 959 net::AuthCredentials* auth_credentials, | 1053 net::AuthCredentials* auth_credentials, |
| 960 std::set<std::string>* conflicting_extensions, | 1054 extensions::ExtensionWarningSet* conflicting_extensions, |
| 961 const net::BoundNetLog* net_log) { | 1055 const net::BoundNetLog* net_log) { |
| 962 CHECK(auth_credentials); | 1056 CHECK(auth_credentials); |
| 963 bool credentials_set = false; | 1057 bool credentials_set = false; |
| 1058 std::string winning_extension_id; |
| 964 | 1059 |
| 965 for (EventResponseDeltas::const_iterator delta = deltas.begin(); | 1060 for (EventResponseDeltas::const_iterator delta = deltas.begin(); |
| 966 delta != deltas.end(); | 1061 delta != deltas.end(); |
| 967 ++delta) { | 1062 ++delta) { |
| 968 if (!(*delta)->auth_credentials.get()) | 1063 if (!(*delta)->auth_credentials.get()) |
| 969 continue; | 1064 continue; |
| 970 bool different = | 1065 bool different = |
| 971 auth_credentials->username() != | 1066 auth_credentials->username() != |
| 972 (*delta)->auth_credentials->username() || | 1067 (*delta)->auth_credentials->username() || |
| 973 auth_credentials->password() != (*delta)->auth_credentials->password(); | 1068 auth_credentials->password() != (*delta)->auth_credentials->password(); |
| 974 if (credentials_set && different) { | 1069 if (credentials_set && different) { |
| 975 conflicting_extensions->insert((*delta)->extension_id); | 1070 conflicting_extensions->insert( |
| 1071 ExtensionWarning::CreateCredentialsConflictWarning( |
| 1072 (*delta)->extension_id, winning_extension_id)); |
| 976 net_log->AddEvent( | 1073 net_log->AddEvent( |
| 977 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 1074 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
| 978 CreateNetLogExtensionIdCallback(delta->get())); | 1075 CreateNetLogExtensionIdCallback(delta->get())); |
| 979 } else { | 1076 } else { |
| 980 net_log->AddEvent( | 1077 net_log->AddEvent( |
| 981 net::NetLog::TYPE_CHROME_EXTENSION_PROVIDE_AUTH_CREDENTIALS, | 1078 net::NetLog::TYPE_CHROME_EXTENSION_PROVIDE_AUTH_CREDENTIALS, |
| 982 CreateNetLogExtensionIdCallback(delta->get())); | 1079 CreateNetLogExtensionIdCallback(delta->get())); |
| 983 *auth_credentials = *(*delta)->auth_credentials; | 1080 *auth_credentials = *(*delta)->auth_credentials; |
| 984 credentials_set = true; | 1081 credentials_set = true; |
| 1082 winning_extension_id = (*delta)->extension_id; |
| 985 } | 1083 } |
| 986 } | 1084 } |
| 987 return credentials_set; | 1085 return credentials_set; |
| 988 } | 1086 } |
| 989 | 1087 |
| 990 | 1088 |
| 991 #define ARRAYEND(array) (array + arraysize(array)) | 1089 #define ARRAYEND(array) (array + arraysize(array)) |
| 992 | 1090 |
| 993 bool IsRelevantResourceType(ResourceType::Type type) { | 1091 bool IsRelevantResourceType(ResourceType::Type type) { |
| 994 ResourceType::Type* iter = | 1092 ResourceType::Type* iter = |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1026 void ClearCacheOnNavigation() { | 1124 void ClearCacheOnNavigation() { |
| 1027 if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { | 1125 if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) { |
| 1028 ClearCacheOnNavigationOnUI(); | 1126 ClearCacheOnNavigationOnUI(); |
| 1029 } else { | 1127 } else { |
| 1030 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 1128 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| 1031 base::Bind(&ClearCacheOnNavigationOnUI)); | 1129 base::Bind(&ClearCacheOnNavigationOnUI)); |
| 1032 } | 1130 } |
| 1033 } | 1131 } |
| 1034 | 1132 |
| 1035 } // namespace extension_web_request_api_helpers | 1133 } // namespace extension_web_request_api_helpers |
| OLD | NEW |