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

Unified Diff: chrome/browser/extensions/extension_webrequest_api_helpers.cc

Issue 8511063: Improve merging of header modifications in webRequest.OnHeadersReceived (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/extension_webrequest_api_helpers.cc
diff --git a/chrome/browser/extensions/extension_webrequest_api_helpers.cc b/chrome/browser/extensions/extension_webrequest_api_helpers.cc
index d9357784c53d30957b4ea059ca09b68d2c6a8b14..22251126f9313f6bf9090774952dbd047e3efee1 100644
--- a/chrome/browser/extensions/extension_webrequest_api_helpers.cc
+++ b/chrome/browser/extensions/extension_webrequest_api_helpers.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/extensions/extension_webrequest_api_helpers.h"
+#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_webrequest_api.h"
#include "net/http/http_util.h"
@@ -165,21 +166,54 @@ EventResponseDelta* CalculateOnHeadersReceivedDelta(
const std::string& extension_id,
const base::Time& extension_install_time,
bool cancel,
- const std::string& status_line,
- const std::string& response_headers_string) {
+ net::HttpResponseHeaders* old_response_headers,
+ ResponseHeaders* new_response_headers) {
EventResponseDelta* result =
new EventResponseDelta(extension_id, extension_install_time);
result->cancel = cancel;
- if (!response_headers_string.empty()) {
- std::string new_headers_string =
- status_line + "\n" + response_headers_string;
+ if (!new_response_headers)
+ return result;
- result->new_response_headers =
- new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(new_headers_string.c_str(),
- new_headers_string.length()));
+ // Find deleted headers (header keys are treated case insensitively).
+ {
+ void* iter = NULL;
+ std::string name;
+ std::string value;
+ while (old_response_headers->EnumerateHeaderLines(&iter, &name, &value)) {
+ std::string name_lowercase(name);
+ StringToLowerASCII(&name_lowercase);
+
+ bool header_found = false;
+ for (ResponseHeaders::const_iterator i = new_response_headers->begin();
+ i != new_response_headers->end(); ++i) {
+ if (LowerCaseEqualsASCII(i->first, name_lowercase.c_str()) &&
+ value == i->second) {
+ header_found = true;
+ break;
+ }
+ }
+ if (!header_found)
+ result->deleted_response_headers.push_back(ResponseHeader(name, value));
+ }
}
+
+ // Find added headers (header keys are treated case insensitively).
+ {
+ for (ResponseHeaders::const_iterator i = new_response_headers->begin();
+ i != new_response_headers->end(); ++i) {
+ void* iter = NULL;
+ std::string value;
+ bool header_found = false;
+ while (old_response_headers->EnumerateHeader(&iter, i->first, &value) &&
+ !header_found) {
+ header_found = (value == i->second);
+ }
+ if (!header_found)
+ result->added_response_headers.push_back(*i);
+ }
+ }
+
return result;
}
@@ -346,33 +380,82 @@ void MergeOnBeforeSendHeadersResponses(
}
}
+// Converts the key of the (key, value) pair to lower case.
+ResponseHeader toLowerCase(const ResponseHeader& header) {
Matt Perry 2011/11/11 22:05:08 ToLowerCase also make this static, or put it in a
battre 2011/11/17 12:01:04 Done.
+ std::string lower_key(header.first);
+ StringToLowerASCII(&lower_key);
+ return ResponseHeader(lower_key, header.second);
+}
+
void MergeOnHeadersReceivedResponses(
const EventResponseDeltas& deltas,
+ const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
std::set<std::string>* conflicting_extensions,
EventLogEntries* event_log_entries) {
EventResponseDeltas::const_iterator delta;
- // Whether any extension has overridden the response headers, yet.
- bool headers_overridden = false;
+ // Here we collect which headers we have removed or added so far due to
+ // extensions of higher precedence. Header keys are always stored as
+ // lower case.
+ std::set<ResponseHeader> removed_headers;
+ std::set<ResponseHeader> added_headers;
// We assume here that the deltas are sorted in decreasing extension
// precedence (i.e. decreasing extension installation time).
for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
- if (!(*delta)->new_response_headers.get())
+ if ((*delta)->added_response_headers.empty() &&
+ (*delta)->deleted_response_headers.empty()) {
continue;
+ }
- scoped_refptr<NetLogModificationParameter> log(
- new NetLogModificationParameter((*delta)->extension_id));
+ // Only create a copy if we really want to modify the response headers.
+ if (override_response_headers->get() == NULL) {
+ *override_response_headers = new net::HttpResponseHeaders(
+ original_response_headers->raw_headers());
+ }
- // Conflict if a second extension returned new response headers;
- bool extension_conflicts = headers_overridden;
+ // We consider modifications as pairs of (delete, add) operations.
+ // If a header is deleted twice by different extensions we assume that the
+ // intention was to modify it to different values and consider this a
Matt Perry 2011/11/11 22:05:08 this seems like a strange assumption to me
battre 2011/11/17 12:01:04 Do you have a better proposal? Say you have a res
Matt Perry 2011/11/17 20:04:09 It still seems possible to me to distinguish betwe
+ // conflict. As deltas is sorted by decreasing extension installation order,
+ // this takes care of precedence.
+ bool extension_conflicts = false;
+ 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()) {
+ extension_conflicts = true;
+ break;
+ }
+ }
+ // Now execute the modifications if there were no conflicts.
if (!extension_conflicts) {
- headers_overridden = true;
- *override_response_headers = (*delta)->new_response_headers;
+ // Delete headers
+ {
+ for (i = (*delta)->deleted_response_headers.begin();
+ i != (*delta)->deleted_response_headers.end(); ++i) {
+ (*override_response_headers)->RemoveHeader(i->first, i->second);
+ removed_headers.insert(toLowerCase(*i));
+ }
+ }
+
+ // Add headers.
+ {
+ for (i = (*delta)->added_response_headers.begin();
+ i != (*delta)->added_response_headers.end(); ++i) {
+ ResponseHeader lowercase_header(toLowerCase(*i));
+ if (added_headers.find(lowercase_header) != added_headers.end())
+ continue;
+ added_headers.insert(lowercase_header);
+ (*override_response_headers)->AddHeader(i->first + ": " + i->second);
+ }
+ }
EventLogEntry log_entry(
- net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, log);
+ net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS,
+ make_scoped_refptr(
+ new NetLogModificationParameter((*delta)->extension_id)));
event_log_entries->push_back(log_entry);
} else {
conflicting_extensions->insert((*delta)->extension_id);

Powered by Google App Engine
This is Rietveld 408576698