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

Side by Side 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: Disabled browser tests again 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/extension_webrequest_api_helpers.h" 5 #include "chrome/browser/extensions/extension_webrequest_api_helpers.h"
6 6
7 #include "base/string_util.h"
7 #include "base/values.h" 8 #include "base/values.h"
8 #include "chrome/browser/extensions/extension_webrequest_api.h" 9 #include "chrome/browser/extensions/extension_webrequest_api.h"
9 #include "net/http/http_util.h" 10 #include "net/http/http_util.h"
10 11
11 namespace extension_webrequest_api_helpers { 12 namespace extension_webrequest_api_helpers {
12 13
13 14
14 EventResponseDelta::EventResponseDelta( 15 EventResponseDelta::EventResponseDelta(
15 const std::string& extension_id, const base::Time& extension_install_time) 16 const std::string& extension_id, const base::Time& extension_install_time)
16 : extension_id(extension_id), 17 : extension_id(extension_id),
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 } 159 }
159 } 160 }
160 } 161 }
161 return result; 162 return result;
162 } 163 }
163 164
164 EventResponseDelta* CalculateOnHeadersReceivedDelta( 165 EventResponseDelta* CalculateOnHeadersReceivedDelta(
165 const std::string& extension_id, 166 const std::string& extension_id,
166 const base::Time& extension_install_time, 167 const base::Time& extension_install_time,
167 bool cancel, 168 bool cancel,
168 const std::string& status_line, 169 net::HttpResponseHeaders* old_response_headers,
169 const std::string& response_headers_string) { 170 ResponseHeaders* new_response_headers) {
170 EventResponseDelta* result = 171 EventResponseDelta* result =
171 new EventResponseDelta(extension_id, extension_install_time); 172 new EventResponseDelta(extension_id, extension_install_time);
172 result->cancel = cancel; 173 result->cancel = cancel;
173 174
174 if (!response_headers_string.empty()) { 175 if (!new_response_headers)
175 std::string new_headers_string = 176 return result;
176 status_line + "\n" + response_headers_string;
177 177
178 result->new_response_headers = 178 // Find deleted headers (header keys are treated case insensitively).
179 new net::HttpResponseHeaders( 179 {
180 net::HttpUtil::AssembleRawHeaders(new_headers_string.c_str(), 180 void* iter = NULL;
181 new_headers_string.length())); 181 std::string name;
182 std::string value;
183 while (old_response_headers->EnumerateHeaderLines(&iter, &name, &value)) {
184 std::string name_lowercase(name);
185 StringToLowerASCII(&name_lowercase);
186
187 bool header_found = false;
188 for (ResponseHeaders::const_iterator i = new_response_headers->begin();
189 i != new_response_headers->end(); ++i) {
190 if (LowerCaseEqualsASCII(i->first, name_lowercase.c_str()) &&
191 value == i->second) {
192 header_found = true;
193 break;
194 }
195 }
196 if (!header_found)
197 result->deleted_response_headers.push_back(ResponseHeader(name, value));
198 }
182 } 199 }
200
201 // Find added headers (header keys are treated case insensitively).
202 {
203 for (ResponseHeaders::const_iterator i = new_response_headers->begin();
204 i != new_response_headers->end(); ++i) {
205 void* iter = NULL;
206 std::string value;
207 bool header_found = false;
208 while (old_response_headers->EnumerateHeader(&iter, i->first, &value) &&
209 !header_found) {
210 header_found = (value == i->second);
211 }
212 if (!header_found)
213 result->added_response_headers.push_back(*i);
214 }
215 }
216
183 return result; 217 return result;
184 } 218 }
185 219
186 EventResponseDelta* CalculateOnAuthRequiredDelta( 220 EventResponseDelta* CalculateOnAuthRequiredDelta(
187 const std::string& extension_id, 221 const std::string& extension_id,
188 const base::Time& extension_install_time, 222 const base::Time& extension_install_time,
189 bool cancel, 223 bool cancel,
190 scoped_ptr<net::AuthCredentials>* auth_credentials) { 224 scoped_ptr<net::AuthCredentials>* auth_credentials) {
191 EventResponseDelta* result = 225 EventResponseDelta* result =
192 new EventResponseDelta(extension_id, extension_install_time); 226 new EventResponseDelta(extension_id, extension_install_time);
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 conflicting_extensions->insert((*delta)->extension_id); 373 conflicting_extensions->insert((*delta)->extension_id);
340 EventLogEntry log_entry( 374 EventLogEntry log_entry(
341 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, 375 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT,
342 make_scoped_refptr( 376 make_scoped_refptr(
343 new NetLogExtensionIdParameter((*delta)->extension_id))); 377 new NetLogExtensionIdParameter((*delta)->extension_id)));
344 event_log_entries->push_back(log_entry); 378 event_log_entries->push_back(log_entry);
345 } 379 }
346 } 380 }
347 } 381 }
348 382
383 // Converts the key of the (key, value) pair to lower case.
384 static ResponseHeader ToLowerCase(const ResponseHeader& header) {
385 std::string lower_key(header.first);
386 StringToLowerASCII(&lower_key);
387 return ResponseHeader(lower_key, header.second);
388 }
389
349 void MergeOnHeadersReceivedResponses( 390 void MergeOnHeadersReceivedResponses(
350 const EventResponseDeltas& deltas, 391 const EventResponseDeltas& deltas,
392 const net::HttpResponseHeaders* original_response_headers,
351 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, 393 scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
352 std::set<std::string>* conflicting_extensions, 394 std::set<std::string>* conflicting_extensions,
353 EventLogEntries* event_log_entries) { 395 EventLogEntries* event_log_entries) {
354 EventResponseDeltas::const_iterator delta; 396 EventResponseDeltas::const_iterator delta;
355 397
356 // Whether any extension has overridden the response headers, yet. 398 // Here we collect which headers we have removed or added so far due to
357 bool headers_overridden = false; 399 // extensions of higher precedence. Header keys are always stored as
400 // lower case.
401 std::set<ResponseHeader> removed_headers;
402 std::set<ResponseHeader> added_headers;
358 403
359 // We assume here that the deltas are sorted in decreasing extension 404 // We assume here that the deltas are sorted in decreasing extension
360 // precedence (i.e. decreasing extension installation time). 405 // precedence (i.e. decreasing extension installation time).
361 for (delta = deltas.begin(); delta != deltas.end(); ++delta) { 406 for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
362 if (!(*delta)->new_response_headers.get()) 407 if ((*delta)->added_response_headers.empty() &&
408 (*delta)->deleted_response_headers.empty()) {
363 continue; 409 continue;
410 }
364 411
365 scoped_refptr<NetLogModificationParameter> log( 412 // Only create a copy if we really want to modify the response headers.
366 new NetLogModificationParameter((*delta)->extension_id)); 413 if (override_response_headers->get() == NULL) {
414 *override_response_headers = new net::HttpResponseHeaders(
415 original_response_headers->raw_headers());
416 }
367 417
368 // Conflict if a second extension returned new response headers; 418 // We consider modifications as pairs of (delete, add) operations.
369 bool extension_conflicts = headers_overridden; 419 // If a header is deleted twice by different extensions we assume that the
420 // intention was to modify it to different values and consider this a
421 // conflict. As deltas is sorted by decreasing extension installation order,
422 // this takes care of precedence.
423 bool extension_conflicts = false;
424 ResponseHeaders::const_iterator i;
425 for (i = (*delta)->deleted_response_headers.begin();
426 i != (*delta)->deleted_response_headers.end(); ++i) {
427 if (removed_headers.find(ToLowerCase(*i)) != removed_headers.end()) {
428 extension_conflicts = true;
429 break;
430 }
431 }
370 432
433 // Now execute the modifications if there were no conflicts.
371 if (!extension_conflicts) { 434 if (!extension_conflicts) {
372 headers_overridden = true; 435 // Delete headers
373 *override_response_headers = (*delta)->new_response_headers; 436 {
437 for (i = (*delta)->deleted_response_headers.begin();
438 i != (*delta)->deleted_response_headers.end(); ++i) {
439 (*override_response_headers)->RemoveHeaderWithValue(i->first,
440 i->second);
441 removed_headers.insert(ToLowerCase(*i));
442 }
443 }
444
445 // Add headers.
446 {
447 for (i = (*delta)->added_response_headers.begin();
448 i != (*delta)->added_response_headers.end(); ++i) {
449 ResponseHeader lowercase_header(ToLowerCase(*i));
450 if (added_headers.find(lowercase_header) != added_headers.end())
451 continue;
452 added_headers.insert(lowercase_header);
453 (*override_response_headers)->AddHeader(i->first + ": " + i->second);
454 }
455 }
374 EventLogEntry log_entry( 456 EventLogEntry log_entry(
375 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS, log); 457 net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS,
458 make_scoped_refptr(
459 new NetLogModificationParameter((*delta)->extension_id)));
376 event_log_entries->push_back(log_entry); 460 event_log_entries->push_back(log_entry);
377 } else { 461 } else {
378 conflicting_extensions->insert((*delta)->extension_id); 462 conflicting_extensions->insert((*delta)->extension_id);
379 EventLogEntry log_entry( 463 EventLogEntry log_entry(
380 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, 464 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT,
381 make_scoped_refptr( 465 make_scoped_refptr(
382 new NetLogExtensionIdParameter((*delta)->extension_id))); 466 new NetLogExtensionIdParameter((*delta)->extension_id)));
383 event_log_entries->push_back(log_entry); 467 event_log_entries->push_back(log_entry);
384 } 468 }
385 } 469 }
(...skipping 30 matching lines...) Expand all
416 new NetLogExtensionIdParameter((*delta)->extension_id))); 500 new NetLogExtensionIdParameter((*delta)->extension_id)));
417 event_log_entries->push_back(log_entry); 501 event_log_entries->push_back(log_entry);
418 *auth_credentials = *(*delta)->auth_credentials; 502 *auth_credentials = *(*delta)->auth_credentials;
419 credentials_set = true; 503 credentials_set = true;
420 } 504 }
421 } 505 }
422 return credentials_set; 506 return credentials_set;
423 } 507 }
424 508
425 } // namespace extension_webrequest_api_helpers 509 } // namespace extension_webrequest_api_helpers
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698