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 <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 } | 317 } |
318 } | 318 } |
319 } | 319 } |
320 return result; | 320 return result; |
321 } | 321 } |
322 | 322 |
323 EventResponseDelta* CalculateOnHeadersReceivedDelta( | 323 EventResponseDelta* CalculateOnHeadersReceivedDelta( |
324 const std::string& extension_id, | 324 const std::string& extension_id, |
325 const base::Time& extension_install_time, | 325 const base::Time& extension_install_time, |
326 bool cancel, | 326 bool cancel, |
| 327 const GURL& new_url, |
327 const net::HttpResponseHeaders* old_response_headers, | 328 const net::HttpResponseHeaders* old_response_headers, |
328 ResponseHeaders* new_response_headers) { | 329 ResponseHeaders* new_response_headers) { |
329 EventResponseDelta* result = | 330 EventResponseDelta* result = |
330 new EventResponseDelta(extension_id, extension_install_time); | 331 new EventResponseDelta(extension_id, extension_install_time); |
331 result->cancel = cancel; | 332 result->cancel = cancel; |
| 333 result->new_url = new_url; |
332 | 334 |
333 if (!new_response_headers) | 335 if (!new_response_headers) |
334 return result; | 336 return result; |
335 | 337 |
336 // Find deleted headers (header keys are treated case insensitively). | 338 // Find deleted headers (header keys are treated case insensitively). |
337 { | 339 { |
338 void* iter = NULL; | 340 void* iter = NULL; |
339 std::string name; | 341 std::string name; |
340 std::string value; | 342 std::string value; |
341 while (old_response_headers->EnumerateHeaderLines(&iter, &name, &value)) { | 343 while (old_response_headers->EnumerateHeaderLines(&iter, &name, &value)) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 if ((*i)->cancel) { | 398 if ((*i)->cancel) { |
397 *canceled = true; | 399 *canceled = true; |
398 net_log->AddEvent( | 400 net_log->AddEvent( |
399 net::NetLog::TYPE_CHROME_EXTENSION_ABORTED_REQUEST, | 401 net::NetLog::TYPE_CHROME_EXTENSION_ABORTED_REQUEST, |
400 CreateNetLogExtensionIdCallback(i->get())); | 402 CreateNetLogExtensionIdCallback(i->get())); |
401 break; | 403 break; |
402 } | 404 } |
403 } | 405 } |
404 } | 406 } |
405 | 407 |
406 // Helper function for MergeOnBeforeRequestResponses() that allows ignoring | 408 // Helper function for MergeRedirectUrlOfResponses() that allows ignoring |
407 // all redirects but those to data:// urls and about:blank. This is important | 409 // all redirects but those to data:// urls and about:blank. This is important |
408 // to treat these URLs as "cancel urls", i.e. URLs that extensions redirect | 410 // to treat these URLs as "cancel urls", i.e. URLs that extensions redirect |
409 // to if they want to express that they want to cancel a request. This reduces | 411 // to if they want to express that they want to cancel a request. This reduces |
410 // the number of conflicts that we need to flag, as canceling is considered | 412 // the number of conflicts that we need to flag, as canceling is considered |
411 // a higher precedence operation that redirects. | 413 // a higher precedence operation that redirects. |
412 // Returns whether a redirect occurred. | 414 // Returns whether a redirect occurred. |
413 static bool MergeOnBeforeRequestResponsesHelper( | 415 static bool MergeRedirectUrlOfResponsesHelper( |
414 const EventResponseDeltas& deltas, | 416 const EventResponseDeltas& deltas, |
415 GURL* new_url, | 417 GURL* new_url, |
416 extensions::ExtensionWarningSet* conflicting_extensions, | 418 extensions::ExtensionWarningSet* conflicting_extensions, |
417 const net::BoundNetLog* net_log, | 419 const net::BoundNetLog* net_log, |
418 bool consider_only_cancel_scheme_urls) { | 420 bool consider_only_cancel_scheme_urls) { |
419 bool redirected = false; | 421 bool redirected = false; |
420 | 422 |
421 // Extension that determines the |new_url|. | 423 // Extension that determines the |new_url|. |
422 std::string winning_extension_id; | 424 std::string winning_extension_id; |
423 EventResponseDeltas::const_iterator delta; | 425 EventResponseDeltas::const_iterator delta; |
(...skipping 21 matching lines...) Expand all Loading... |
445 (*delta)->new_url, | 447 (*delta)->new_url, |
446 *new_url)); | 448 *new_url)); |
447 net_log->AddEvent( | 449 net_log->AddEvent( |
448 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 450 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
449 CreateNetLogExtensionIdCallback(delta->get())); | 451 CreateNetLogExtensionIdCallback(delta->get())); |
450 } | 452 } |
451 } | 453 } |
452 return redirected; | 454 return redirected; |
453 } | 455 } |
454 | 456 |
455 void MergeOnBeforeRequestResponses( | 457 void MergeRedirectUrlOfResponses( |
456 const EventResponseDeltas& deltas, | 458 const EventResponseDeltas& deltas, |
457 GURL* new_url, | 459 GURL* new_url, |
458 extensions::ExtensionWarningSet* conflicting_extensions, | 460 extensions::ExtensionWarningSet* conflicting_extensions, |
459 const net::BoundNetLog* net_log) { | 461 const net::BoundNetLog* net_log) { |
460 | 462 |
461 // First handle only redirects to data:// URLs and about:blank. These are a | 463 // First handle only redirects to data:// URLs and about:blank. These are a |
462 // special case as they represent a way of cancelling a request. | 464 // special case as they represent a way of cancelling a request. |
463 if (MergeOnBeforeRequestResponsesHelper( | 465 if (MergeRedirectUrlOfResponsesHelper( |
464 deltas, new_url, conflicting_extensions, net_log, true)) { | 466 deltas, new_url, conflicting_extensions, net_log, true)) { |
465 // If any extension cancelled a request by redirecting to a data:// URL or | 467 // If any extension cancelled a request by redirecting to a data:// URL or |
466 // about:blank, we don't consider the other redirects. | 468 // about:blank, we don't consider the other redirects. |
467 return; | 469 return; |
468 } | 470 } |
469 | 471 |
470 // Handle all other redirects. | 472 // Handle all other redirects. |
471 MergeOnBeforeRequestResponsesHelper( | 473 MergeRedirectUrlOfResponsesHelper( |
472 deltas, new_url, conflicting_extensions, net_log, false); | 474 deltas, new_url, conflicting_extensions, net_log, false); |
473 } | 475 } |
474 | 476 |
| 477 void MergeOnBeforeRequestResponses( |
| 478 const EventResponseDeltas& deltas, |
| 479 GURL* new_url, |
| 480 extensions::ExtensionWarningSet* conflicting_extensions, |
| 481 const net::BoundNetLog* net_log) { |
| 482 MergeRedirectUrlOfResponses(deltas, new_url, conflicting_extensions, net_log); |
| 483 } |
| 484 |
475 // Assumes that |header_value| is the cookie header value of a HTTP Request | 485 // Assumes that |header_value| is the cookie header value of a HTTP Request |
476 // following the cookie-string schema of RFC 6265, section 4.2.1, and returns | 486 // following the cookie-string schema of RFC 6265, section 4.2.1, and returns |
477 // cookie name/value pairs. If cookie values are presented in double quotes, | 487 // cookie name/value pairs. If cookie values are presented in double quotes, |
478 // these will appear in |parsed| as well. We can assume that the cookie header | 488 // these will appear in |parsed| as well. We can assume that the cookie header |
479 // is written by Chromium and therefore, well-formed. | 489 // is written by Chromium and therefore, well-formed. |
480 static void ParseRequestCookieLine( | 490 static void ParseRequestCookieLine( |
481 const std::string& header_value, | 491 const std::string& header_value, |
482 ParsedRequestCookies* parsed_cookies) { | 492 ParsedRequestCookies* parsed_cookies) { |
483 std::string::const_iterator i = header_value.begin(); | 493 std::string::const_iterator i = header_value.begin(); |
484 while (i != header_value.end()) { | 494 while (i != header_value.end()) { |
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 return (*delta)->extension_id; | 1103 return (*delta)->extension_id; |
1094 } | 1104 } |
1095 } | 1105 } |
1096 return std::string(); | 1106 return std::string(); |
1097 } | 1107 } |
1098 | 1108 |
1099 void MergeOnHeadersReceivedResponses( | 1109 void MergeOnHeadersReceivedResponses( |
1100 const EventResponseDeltas& deltas, | 1110 const EventResponseDeltas& deltas, |
1101 const net::HttpResponseHeaders* original_response_headers, | 1111 const net::HttpResponseHeaders* original_response_headers, |
1102 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, | 1112 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, |
| 1113 GURL* allowed_unsafe_redirect_url, |
1103 extensions::ExtensionWarningSet* conflicting_extensions, | 1114 extensions::ExtensionWarningSet* conflicting_extensions, |
1104 const net::BoundNetLog* net_log) { | 1115 const net::BoundNetLog* net_log) { |
1105 EventResponseDeltas::const_iterator delta; | 1116 EventResponseDeltas::const_iterator delta; |
1106 | 1117 |
1107 // Here we collect which headers we have removed or added so far due to | 1118 // Here we collect which headers we have removed or added so far due to |
1108 // extensions of higher precedence. Header keys are always stored as | 1119 // extensions of higher precedence. Header keys are always stored as |
1109 // lower case. | 1120 // lower case. |
1110 std::set<ResponseHeader> removed_headers; | 1121 std::set<ResponseHeader> removed_headers; |
1111 std::set<ResponseHeader> added_headers; | 1122 std::set<ResponseHeader> added_headers; |
1112 | 1123 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1174 (*delta)->extension_id, winning_extension_id, | 1185 (*delta)->extension_id, winning_extension_id, |
1175 conflicting_header)); | 1186 conflicting_header)); |
1176 net_log->AddEvent( | 1187 net_log->AddEvent( |
1177 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, | 1188 net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT, |
1178 CreateNetLogExtensionIdCallback(delta->get())); | 1189 CreateNetLogExtensionIdCallback(delta->get())); |
1179 } | 1190 } |
1180 } | 1191 } |
1181 | 1192 |
1182 MergeCookiesInOnHeadersReceivedResponses(deltas, original_response_headers, | 1193 MergeCookiesInOnHeadersReceivedResponses(deltas, original_response_headers, |
1183 override_response_headers, conflicting_extensions, net_log); | 1194 override_response_headers, conflicting_extensions, net_log); |
| 1195 |
| 1196 GURL new_url; |
| 1197 MergeRedirectUrlOfResponses( |
| 1198 deltas, &new_url, conflicting_extensions, net_log); |
| 1199 if (new_url.is_valid()) { |
| 1200 // Only create a copy if we really want to modify the response headers. |
| 1201 if (override_response_headers->get() == NULL) { |
| 1202 *override_response_headers = new net::HttpResponseHeaders( |
| 1203 original_response_headers->raw_headers()); |
| 1204 } |
| 1205 (*override_response_headers)->ReplaceStatusLine("HTTP/1.1 302 Found"); |
| 1206 (*override_response_headers)->RemoveHeader("location"); |
| 1207 (*override_response_headers)->AddHeader("Location: " + new_url.spec()); |
| 1208 // Explicitly mark the URL as safe for redirection, to prevent the request |
| 1209 // from being blocked because of net::ERR_UNSAFE_REDIRECT. |
| 1210 *allowed_unsafe_redirect_url = new_url; |
| 1211 } |
1184 } | 1212 } |
1185 | 1213 |
1186 bool MergeOnAuthRequiredResponses( | 1214 bool MergeOnAuthRequiredResponses( |
1187 const EventResponseDeltas& deltas, | 1215 const EventResponseDeltas& deltas, |
1188 net::AuthCredentials* auth_credentials, | 1216 net::AuthCredentials* auth_credentials, |
1189 extensions::ExtensionWarningSet* conflicting_extensions, | 1217 extensions::ExtensionWarningSet* conflicting_extensions, |
1190 const net::BoundNetLog* net_log) { | 1218 const net::BoundNetLog* net_log) { |
1191 CHECK(auth_credentials); | 1219 CHECK(auth_credentials); |
1192 bool credentials_set = false; | 1220 bool credentials_set = false; |
1193 std::string winning_extension_id; | 1221 std::string winning_extension_id; |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1286 return net::HttpUtil::IsToken(name); | 1314 return net::HttpUtil::IsToken(name); |
1287 } | 1315 } |
1288 | 1316 |
1289 bool IsValidHeaderValue(const std::string& value) { | 1317 bool IsValidHeaderValue(const std::string& value) { |
1290 // Just a sanity check: disallow NUL and CRLF. | 1318 // Just a sanity check: disallow NUL and CRLF. |
1291 return value.find('\0') == std::string::npos && | 1319 return value.find('\0') == std::string::npos && |
1292 value.find("\r\n") == std::string::npos; | 1320 value.find("\r\n") == std::string::npos; |
1293 } | 1321 } |
1294 | 1322 |
1295 } // namespace extension_web_request_api_helpers | 1323 } // namespace extension_web_request_api_helpers |
OLD | NEW |