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

Side by Side Diff: chrome/browser/extensions/api/web_request/web_request_api_helpers.cc

Issue 10407105: Improve error messaging of webRequest API in case of conflicts (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed Evan's comments Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/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
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
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
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, &current_value) || 692 if (!request_headers->GetHeader(key, &current_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, &current_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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698