| Index: chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
|
| diff --git a/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc b/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
|
| index faca61a38f29bb699ef66693534b63efe5f1e82d..d055ebfc97d9412a9f8e533096165a9aa9b8d184 100644
|
| --- a/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
|
| +++ b/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
|
| @@ -10,6 +10,7 @@
|
| #include "base/stringprintf.h"
|
| #include "base/values.h"
|
| #include "chrome/browser/extensions/api/web_request/web_request_api.h"
|
| +#include "chrome/browser/extensions/extension_warning_set.h"
|
| #include "chrome/browser/renderer_host/web_cache_manager.h"
|
| #include "chrome/common/url_constants.h"
|
| #include "content/public/browser/browser_thread.h"
|
| @@ -18,6 +19,11 @@
|
| #include "net/http/http_util.h"
|
| #include "net/url_request/url_request.h"
|
|
|
| +// TODO(battre): move all static functions into an anonymous namespace at the
|
| +// top of this file.
|
| +
|
| +using extensions::ExtensionWarning;
|
| +
|
| namespace extension_web_request_api_helpers {
|
|
|
| namespace {
|
| @@ -298,11 +304,13 @@ void MergeCancelOfResponses(
|
| static bool MergeOnBeforeRequestResponsesHelper(
|
| const EventResponseDeltas& deltas,
|
| GURL* new_url,
|
| - std::set<std::string>* conflicting_extensions,
|
| + extensions::ExtensionWarningSet* conflicting_extensions,
|
| const net::BoundNetLog* net_log,
|
| bool consider_only_cancel_scheme_urls) {
|
| bool redirected = false;
|
|
|
| + // Extension that determines the |new_url|.
|
| + std::string winning_extension_id;
|
| EventResponseDeltas::const_iterator delta;
|
| for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
|
| if ((*delta)->new_url.is_empty())
|
| @@ -315,12 +323,18 @@ static bool MergeOnBeforeRequestResponsesHelper(
|
|
|
| if (!redirected || *new_url == (*delta)->new_url) {
|
| *new_url = (*delta)->new_url;
|
| + winning_extension_id = (*delta)->extension_id;
|
| redirected = true;
|
| net_log->AddEvent(
|
| net::NetLog::TYPE_CHROME_EXTENSION_REDIRECTED_REQUEST,
|
| CreateNetLogExtensionIdCallback(delta->get()));
|
| } else {
|
| - conflicting_extensions->insert((*delta)->extension_id);
|
| + conflicting_extensions->insert(
|
| + ExtensionWarning::CreateRedirectConflictWarning(
|
| + (*delta)->extension_id,
|
| + winning_extension_id,
|
| + (*delta)->new_url,
|
| + *new_url));
|
| net_log->AddEvent(
|
| net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT,
|
| CreateNetLogExtensionIdCallback(delta->get()));
|
| @@ -332,7 +346,7 @@ static bool MergeOnBeforeRequestResponsesHelper(
|
| void MergeOnBeforeRequestResponses(
|
| const EventResponseDeltas& deltas,
|
| GURL* new_url,
|
| - std::set<std::string>* conflicting_extensions,
|
| + extensions::ExtensionWarningSet* conflicting_extensions,
|
| const net::BoundNetLog* net_log) {
|
|
|
| // First handle only redirects to data:// URLs and about:blank. These are a
|
| @@ -530,7 +544,7 @@ static bool MergeRemoveRequestCookieModifications(
|
| void MergeCookiesInOnBeforeSendHeadersResponses(
|
| const EventResponseDeltas& deltas,
|
| net::HttpRequestHeaders* request_headers,
|
| - std::set<std::string>* conflicting_extensions,
|
| + extensions::ExtensionWarningSet* conflicting_extensions,
|
| const net::BoundNetLog* net_log) {
|
| // Skip all work if there are no registered cookie modifications.
|
| bool cookie_modifications_exist = false;
|
| @@ -562,10 +576,46 @@ void MergeCookiesInOnBeforeSendHeadersResponses(
|
| }
|
| }
|
|
|
| +// Returns the extension ID of the first extension in |deltas| that sets the
|
| +// request header identified by |key| to |value|.
|
| +static std::string FindSetRequestHeader(
|
| + const EventResponseDeltas& deltas,
|
| + const std::string& key,
|
| + const std::string& value) {
|
| + EventResponseDeltas::const_iterator delta;
|
| + for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
|
| + net::HttpRequestHeaders::Iterator modification(
|
| + (*delta)->modified_request_headers);
|
| + while (modification.GetNext()) {
|
| + if (key == modification.name() && value == modification.value())
|
| + return (*delta)->extension_id;
|
| + }
|
| + }
|
| + return "";
|
| +}
|
| +
|
| +// Returns the extension ID of the first extension in |deltas| that removes the
|
| +// request header identified by |key|.
|
| +static std::string FindRemoveRequestHeader(
|
| + const EventResponseDeltas& deltas,
|
| + const std::string& key) {
|
| + EventResponseDeltas::const_iterator delta;
|
| + for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
|
| + std::vector<std::string>::iterator i;
|
| + for (i = (*delta)->deleted_request_headers.begin();
|
| + i != (*delta)->deleted_request_headers.end();
|
| + ++i) {
|
| + if (*i == key)
|
| + return (*delta)->extension_id;
|
| + }
|
| + }
|
| + return "";
|
| +}
|
| +
|
| void MergeOnBeforeSendHeadersResponses(
|
| const EventResponseDeltas& deltas,
|
| net::HttpRequestHeaders* request_headers,
|
| - std::set<std::string>* conflicting_extensions,
|
| + extensions::ExtensionWarningSet* conflicting_extensions,
|
| const net::BoundNetLog* net_log) {
|
| EventResponseDeltas::const_iterator delta;
|
|
|
| @@ -586,6 +636,8 @@ void MergeOnBeforeSendHeadersResponses(
|
| // has been modified differently before. As deltas is sorted by decreasing
|
| // extension installation order, this takes care of precedence.
|
| bool extension_conflicts = false;
|
| + std::string winning_extension_id;
|
| + std::string conflicting_header;
|
| {
|
| net::HttpRequestHeaders::Iterator modification(
|
| (*delta)->modified_request_headers);
|
| @@ -595,15 +647,23 @@ void MergeOnBeforeSendHeadersResponses(
|
| const std::string& value = modification.value();
|
|
|
| // We must not delete anything that has been modified before.
|
| - if (removed_headers.find(key) != removed_headers.end())
|
| + if (removed_headers.find(key) != removed_headers.end() &&
|
| + !extension_conflicts) {
|
| + winning_extension_id = FindRemoveRequestHeader(deltas, key);
|
| + conflicting_header = key;
|
| extension_conflicts = true;
|
| + }
|
|
|
| // We must not modify anything that has been set to a *different*
|
| // value before.
|
| - if (set_headers.find(key) != set_headers.end()) {
|
| + if (set_headers.find(key) != set_headers.end() &&
|
| + !extension_conflicts) {
|
| std::string current_value;
|
| if (!request_headers->GetHeader(key, ¤t_value) ||
|
| current_value != value) {
|
| + winning_extension_id =
|
| + FindSetRequestHeader(deltas, key, current_value);
|
| + conflicting_header = key;
|
| extension_conflicts = true;
|
| }
|
| }
|
| @@ -618,8 +678,14 @@ void MergeOnBeforeSendHeadersResponses(
|
| key != (*delta)->deleted_request_headers.end() &&
|
| !extension_conflicts;
|
| ++key) {
|
| - if (set_headers.find(*key) != set_headers.end())
|
| + if (set_headers.find(*key) != set_headers.end()) {
|
| + std::string current_value;
|
| + request_headers->GetHeader(*key, ¤t_value);
|
| + winning_extension_id =
|
| + FindSetRequestHeader(deltas, *key, current_value);
|
| + conflicting_header = *key;
|
| extension_conflicts = true;
|
| + }
|
| }
|
| }
|
|
|
| @@ -649,7 +715,10 @@ void MergeOnBeforeSendHeadersResponses(
|
| net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS,
|
| base::Bind(&NetLogModificationCallback, delta->get()));
|
| } else {
|
| - conflicting_extensions->insert((*delta)->extension_id);
|
| + conflicting_extensions->insert(
|
| + ExtensionWarning::CreateRequestHeaderConflictWarning(
|
| + (*delta)->extension_id, winning_extension_id,
|
| + conflicting_header));
|
| net_log->AddEvent(
|
| net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT,
|
| CreateNetLogExtensionIdCallback(delta->get()));
|
| @@ -836,7 +905,7 @@ void MergeCookiesInOnHeadersReceivedResponses(
|
| const EventResponseDeltas& deltas,
|
| const net::HttpResponseHeaders* original_response_headers,
|
| scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
|
| - std::set<std::string>* conflicting_extensions,
|
| + extensions::ExtensionWarningSet* conflicting_extensions,
|
| const net::BoundNetLog* net_log) {
|
| // Skip all work if there are no registered cookie modifications.
|
| bool cookie_modifications_exist = false;
|
| @@ -874,11 +943,29 @@ static ResponseHeader ToLowerCase(const ResponseHeader& header) {
|
| return ResponseHeader(lower_key, header.second);
|
| }
|
|
|
| +// Returns the extension ID of the first extension in |deltas| that removes the
|
| +// request header identified by |key|.
|
| +static std::string FindRemoveResponseHeader(
|
| + const EventResponseDeltas& deltas,
|
| + const std::string& key) {
|
| + std::string lower_key = StringToLowerASCII(key);
|
| + EventResponseDeltas::const_iterator delta;
|
| + for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
|
| + ResponseHeaders::const_iterator i;
|
| + for (i = (*delta)->deleted_response_headers.begin();
|
| + i != (*delta)->deleted_response_headers.end(); ++i) {
|
| + if (StringToLowerASCII(i->first) == lower_key)
|
| + return (*delta)->extension_id;
|
| + }
|
| + }
|
| + return "";
|
| +}
|
| +
|
| void MergeOnHeadersReceivedResponses(
|
| const EventResponseDeltas& deltas,
|
| const net::HttpResponseHeaders* original_response_headers,
|
| scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
|
| - std::set<std::string>* conflicting_extensions,
|
| + extensions::ExtensionWarningSet* conflicting_extensions,
|
| const net::BoundNetLog* net_log) {
|
| EventResponseDeltas::const_iterator delta;
|
|
|
| @@ -908,10 +995,14 @@ void MergeOnHeadersReceivedResponses(
|
| // conflict. As deltas is sorted by decreasing extension installation order,
|
| // this takes care of precedence.
|
| bool extension_conflicts = false;
|
| + std::string conflicting_header;
|
| + std::string winning_extension_id;
|
| ResponseHeaders::const_iterator i;
|
| for (i = (*delta)->deleted_response_headers.begin();
|
| i != (*delta)->deleted_response_headers.end(); ++i) {
|
| if (removed_headers.find(ToLowerCase(*i)) != removed_headers.end()) {
|
| + winning_extension_id = FindRemoveResponseHeader(deltas, i->first);
|
| + conflicting_header = i->first;
|
| extension_conflicts = true;
|
| break;
|
| }
|
| @@ -943,7 +1034,10 @@ void MergeOnHeadersReceivedResponses(
|
| net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS,
|
| CreateNetLogExtensionIdCallback(delta->get()));
|
| } else {
|
| - conflicting_extensions->insert((*delta)->extension_id);
|
| + conflicting_extensions->insert(
|
| + ExtensionWarning::CreateResponseHeaderConflictWarning(
|
| + (*delta)->extension_id, winning_extension_id,
|
| + conflicting_header));
|
| net_log->AddEvent(
|
| net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT,
|
| CreateNetLogExtensionIdCallback(delta->get()));
|
| @@ -957,10 +1051,11 @@ void MergeOnHeadersReceivedResponses(
|
| bool MergeOnAuthRequiredResponses(
|
| const EventResponseDeltas& deltas,
|
| net::AuthCredentials* auth_credentials,
|
| - std::set<std::string>* conflicting_extensions,
|
| + extensions::ExtensionWarningSet* conflicting_extensions,
|
| const net::BoundNetLog* net_log) {
|
| CHECK(auth_credentials);
|
| bool credentials_set = false;
|
| + std::string winning_extension_id;
|
|
|
| for (EventResponseDeltas::const_iterator delta = deltas.begin();
|
| delta != deltas.end();
|
| @@ -972,7 +1067,9 @@ bool MergeOnAuthRequiredResponses(
|
| (*delta)->auth_credentials->username() ||
|
| auth_credentials->password() != (*delta)->auth_credentials->password();
|
| if (credentials_set && different) {
|
| - conflicting_extensions->insert((*delta)->extension_id);
|
| + conflicting_extensions->insert(
|
| + ExtensionWarning::CreateCredentialsConflictWarning(
|
| + (*delta)->extension_id, winning_extension_id));
|
| net_log->AddEvent(
|
| net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT,
|
| CreateNetLogExtensionIdCallback(delta->get()));
|
| @@ -982,6 +1079,7 @@ bool MergeOnAuthRequiredResponses(
|
| CreateNetLogExtensionIdCallback(delta->get()));
|
| *auth_credentials = *(*delta)->auth_credentials;
|
| credentials_set = true;
|
| + winning_extension_id = (*delta)->extension_id;
|
| }
|
| }
|
| return credentials_set;
|
|
|