Chromium Code Reviews| 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 "net/url_request/url_request_job.h" | 5 #include "net/url_request/url_request_job.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/power_monitor/power_monitor.h" | 13 #include "base/power_monitor/power_monitor.h" |
| 14 #include "base/profiler/scoped_tracker.h" | 14 #include "base/profiler/scoped_tracker.h" |
| 15 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
| 16 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/strings/string_split.h" | |
| 17 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 18 #include "base/threading/thread_task_runner_handle.h" | 19 #include "base/threading/thread_task_runner_handle.h" |
| 19 #include "base/values.h" | 20 #include "base/values.h" |
| 20 #include "net/base/auth.h" | 21 #include "net/base/auth.h" |
| 21 #include "net/base/host_port_pair.h" | 22 #include "net/base/host_port_pair.h" |
| 22 #include "net/base/io_buffer.h" | 23 #include "net/base/io_buffer.h" |
| 23 #include "net/base/load_flags.h" | 24 #include "net/base/load_flags.h" |
| 24 #include "net/base/load_states.h" | 25 #include "net/base/load_states.h" |
| 25 #include "net/base/net_errors.h" | 26 #include "net/base/net_errors.h" |
| 26 #include "net/base/network_delegate.h" | 27 #include "net/base/network_delegate.h" |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 55 // See: | 56 // See: |
| 56 // https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-17#section-7.3 | 57 // https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-17#section-7.3 |
| 57 if ((http_status_code == 303 && method != "HEAD") || | 58 if ((http_status_code == 303 && method != "HEAD") || |
| 58 ((http_status_code == 301 || http_status_code == 302) && | 59 ((http_status_code == 301 || http_status_code == 302) && |
| 59 method == "POST")) { | 60 method == "POST")) { |
| 60 return "GET"; | 61 return "GET"; |
| 61 } | 62 } |
| 62 return method; | 63 return method; |
| 63 } | 64 } |
| 64 | 65 |
| 66 // Given a referrer policy |token| (from the list of policies defined in | |
| 67 // https://w3c.github.io/webappsec-referrer-policy/#referrer-policies), | |
| 68 // this function sets |new_referrer_policy| to the new referrer policy that | |
| 69 // should be used, and sets |new_referrer_source| to the value that | |
| 70 // should be used as input to ComputeReferrerForRedirect(). | |
| 71 // ComputeReferrerForRedirect() is responsible for applying the | |
| 72 // request's URLRequest::ReferrerPolicy to compute the final referrer. | |
| 73 // | |
| 74 // If |token| does not match any policy, then this function does not | |
| 75 // modify |new_referrer_policy| or |new_referrer_source|. | |
| 76 // | |
| 77 // Note that | |
| 78 // https://w3c.github.io/webappsec-referrer-policy/#determine-policy-for-token | |
| 79 // defines legacy keywords "never", "default", and "always", which this | |
| 80 // function respects even though authors are discouraged from using them. | |
| 81 void GetReferrerPolicyFromToken(const std::string& token, | |
| 82 const std::string& referrer_source, | |
| 83 URLRequest::ReferrerPolicy* new_referrer_policy, | |
| 84 std::string* new_referrer_source) { | |
|
mmenke
2016/06/27 18:38:05
"source" is a really confusing name. It's actuall
estark
2016/06/27 22:18:34
Heh, I called it "referrer source" because I found
mmenke
2016/06/28 14:29:23
"referrer_source" sounds like the source of the re
| |
| 85 // For a referrer policy of 'no-referrer', clear the referrer | |
| 86 // source. With an empty referrer source, the request's referrer | |
| 87 // policy doesn't really matter because the final referrer will always | |
| 88 // be empty. | |
| 89 if (base::CompareCaseInsensitiveASCII(token, "never") == 0 || | |
| 90 base::CompareCaseInsensitiveASCII(token, "no-referrer") == 0) { | |
| 91 *new_referrer_policy = URLRequest::NEVER_CLEAR_REFERRER; | |
| 92 *new_referrer_source = std::string(); | |
| 93 return; | |
| 94 } | |
| 95 | |
| 96 // For a referrer policy of 'no-referrer-when-downgrade', setting the | |
| 97 // referrer policy is sufficient; ComputeReferrerForRedirect() will | |
| 98 // apply this policy to strip the referrer if necessary. | |
| 99 if (base::CompareCaseInsensitiveASCII(token, "default") == 0 || | |
| 100 base::CompareCaseInsensitiveASCII(token, "no-referrer-when-downgrade") == | |
| 101 0) { | |
| 102 *new_referrer_policy = | |
| 103 URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE; | |
| 104 *new_referrer_source = referrer_source; | |
| 105 return; | |
| 106 } | |
| 107 | |
| 108 // For a referrer policy of 'origin', strip the referrer source to the | |
| 109 // origin. After doing so, there is no need to modify the referrer | |
| 110 // further, so set the policy to leave the referrer alone. | |
| 111 if (base::CompareCaseInsensitiveASCII(token, "origin") == 0) { | |
| 112 *new_referrer_policy = URLRequest::NEVER_CLEAR_REFERRER; | |
| 113 *new_referrer_source = GURL(referrer_source).GetOrigin().spec(); | |
| 114 return; | |
| 115 } | |
| 116 | |
| 117 // For a referrer policy of 'origin-when-cross-origin', setting the | |
| 118 // URLRequest's ReferrerPolicy is sufficient; | |
| 119 // ComputeReferrerForRedirect() will apply this policy to strip the | |
| 120 // referrer if necessary. | |
| 121 if (base::CompareCaseInsensitiveASCII(token, "origin-when-cross-origin") == | |
| 122 0) { | |
| 123 *new_referrer_policy = URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN; | |
| 124 *new_referrer_source = referrer_source; | |
| 125 return; | |
| 126 } | |
| 127 | |
| 128 // For a referrer policy of 'unsafe-url', leave the referrer source | |
| 129 // untouched and set the policy so that ComputeReferrerForRedirect() | |
| 130 // will not modify it. | |
| 131 if (base::CompareCaseInsensitiveASCII(token, "always") == 0 || | |
| 132 base::CompareCaseInsensitiveASCII(token, "unsafe-url") == 0) { | |
| 133 *new_referrer_policy = URLRequest::NEVER_CLEAR_REFERRER; | |
| 134 *new_referrer_source = referrer_source; | |
| 135 return; | |
| 136 } | |
| 137 | |
| 138 return; | |
| 139 } | |
| 140 | |
| 141 // A redirect response can contain a Referrer-Policy header | |
| 142 // (https://w3c.github.io/webappsec-referrer-policy/). This function | |
| 143 // checks for a Referrer-Policy header, and parses it if | |
| 144 // present. Returns the referrer policy that should be used for the | |
| 145 // request. Sets |new_referrer_source| to the URL that should be used as | |
| 146 // what the spec calls the "referrerSource" -- that is, the referrer | |
| 147 // that will be used as input to ComputeReferrerForRedirect(). | |
| 148 URLRequest::ReferrerPolicy ProcessReferrerPolicyHeaderOnRedirect( | |
| 149 URLRequest* request, | |
| 150 std::string* new_referrer_source) { | |
| 151 URLRequest::ReferrerPolicy new_policy = request->referrer_policy(); | |
| 152 *new_referrer_source = request->referrer(); | |
| 153 | |
| 154 std::string referrer_policy_header; | |
| 155 request->GetResponseHeaderByName("Referrer-Policy", &referrer_policy_header); | |
| 156 std::vector<std::string> policy_tokens = | |
| 157 base::SplitString(referrer_policy_header, ",", base::TRIM_WHITESPACE, | |
| 158 base::SPLIT_WANT_NONEMPTY); | |
| 159 | |
| 160 for (const auto& token : policy_tokens) { | |
| 161 GetReferrerPolicyFromToken(token, request->referrer(), &new_policy, | |
| 162 new_referrer_source); | |
| 163 } | |
| 164 return new_policy; | |
| 165 } | |
| 166 | |
| 65 } // namespace | 167 } // namespace |
| 66 | 168 |
| 67 URLRequestJob::URLRequestJob(URLRequest* request, | 169 URLRequestJob::URLRequestJob(URLRequest* request, |
| 68 NetworkDelegate* network_delegate) | 170 NetworkDelegate* network_delegate) |
| 69 : request_(request), | 171 : request_(request), |
| 70 done_(false), | 172 done_(false), |
| 71 prefilter_bytes_read_(0), | 173 prefilter_bytes_read_(0), |
| 72 postfilter_bytes_read_(0), | 174 postfilter_bytes_read_(0), |
| 73 filter_needs_more_output_space_(false), | 175 filter_needs_more_output_space_(false), |
| 74 filtered_read_buffer_len_(0), | 176 filtered_read_buffer_len_(0), |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 return GURL(); | 439 return GURL(); |
| 338 } else { | 440 } else { |
| 339 return original_referrer.GetOrigin(); | 441 return original_referrer.GetOrigin(); |
| 340 } | 442 } |
| 341 | 443 |
| 342 case URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN: | 444 case URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN: |
| 343 return same_origin ? original_referrer : original_referrer.GetOrigin(); | 445 return same_origin ? original_referrer : original_referrer.GetOrigin(); |
| 344 | 446 |
| 345 case URLRequest::NEVER_CLEAR_REFERRER: | 447 case URLRequest::NEVER_CLEAR_REFERRER: |
| 346 return original_referrer; | 448 return original_referrer; |
| 449 case URLRequest::MAX_REFERRER_POLICY: | |
| 450 NOTREACHED(); | |
| 451 return original_referrer; | |
| 347 } | 452 } |
| 348 | 453 |
| 349 NOTREACHED(); | 454 NOTREACHED(); |
| 350 return GURL(); | 455 return GURL(); |
| 351 } | 456 } |
| 352 | 457 |
| 353 void URLRequestJob::NotifyCertificateRequested( | 458 void URLRequestJob::NotifyCertificateRequested( |
| 354 SSLCertRequestInfo* cert_request_info) { | 459 SSLCertRequestInfo* cert_request_info) { |
| 355 request_->NotifyCertificateRequested(cert_request_info); | 460 request_->NotifyCertificateRequested(cert_request_info); |
| 356 } | 461 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 391 // the time stamps if it has that information. The default request_time is | 496 // the time stamps if it has that information. The default request_time is |
| 392 // set by URLRequest before it calls our Start method. | 497 // set by URLRequest before it calls our Start method. |
| 393 request_->response_info_.response_time = base::Time::Now(); | 498 request_->response_info_.response_time = base::Time::Now(); |
| 394 GetResponseInfo(&request_->response_info_); | 499 GetResponseInfo(&request_->response_info_); |
| 395 | 500 |
| 396 MaybeNotifyNetworkBytes(); | 501 MaybeNotifyNetworkBytes(); |
| 397 request_->OnHeadersComplete(); | 502 request_->OnHeadersComplete(); |
| 398 | 503 |
| 399 GURL new_location; | 504 GURL new_location; |
| 400 int http_status_code; | 505 int http_status_code; |
| 506 | |
| 401 if (IsRedirectResponse(&new_location, &http_status_code)) { | 507 if (IsRedirectResponse(&new_location, &http_status_code)) { |
| 402 // Redirect response bodies are not read. Notify the transaction | 508 // Redirect response bodies are not read. Notify the transaction |
| 403 // so it does not treat being stopped as an error. | 509 // so it does not treat being stopped as an error. |
| 404 DoneReadingRedirectResponse(); | 510 DoneReadingRedirectResponse(); |
| 405 | 511 |
| 406 // When notifying the URLRequest::Delegate, it can destroy the request, | 512 // When notifying the URLRequest::Delegate, it can destroy the request, |
| 407 // which will destroy |this|. After calling to the URLRequest::Delegate, | 513 // which will destroy |this|. After calling to the URLRequest::Delegate, |
| 408 // pointer must be checked to see if |this| still exists, and if not, the | 514 // pointer must be checked to see if |this| still exists, and if not, the |
| 409 // code must return immediately. | 515 // code must return immediately. |
| 410 base::WeakPtr<URLRequestJob> weak_this(weak_factory_.GetWeakPtr()); | 516 base::WeakPtr<URLRequestJob> weak_this(weak_factory_.GetWeakPtr()); |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 937 | 1043 |
| 938 // Update the first-party URL if appropriate. | 1044 // Update the first-party URL if appropriate. |
| 939 if (request_->first_party_url_policy() == | 1045 if (request_->first_party_url_policy() == |
| 940 URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT) { | 1046 URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT) { |
| 941 redirect_info.new_first_party_for_cookies = redirect_info.new_url; | 1047 redirect_info.new_first_party_for_cookies = redirect_info.new_url; |
| 942 } else { | 1048 } else { |
| 943 redirect_info.new_first_party_for_cookies = | 1049 redirect_info.new_first_party_for_cookies = |
| 944 request_->first_party_for_cookies(); | 1050 request_->first_party_for_cookies(); |
| 945 } | 1051 } |
| 946 | 1052 |
| 1053 // |referrer_source| is the starting-point referrer, which may be | |
| 1054 // modified by ComputeReferrerForRedirect() to produce a new referrer | |
| 1055 // that obeys the request's referrer policy. | |
| 1056 std::string referrer_source; | |
| 1057 if (request_->context()->enable_referrer_policy_header()) { | |
|
mmenke
2016/06/27 17:18:04
Question...I may have asked this before, but it se
mmenke
2016/06/27 17:20:04
That is, Site C is not secure, and not on the same
estark
2016/06/27 17:27:52
That does seem weird, but I'm pretty sure that's b
| |
| 1058 redirect_info.new_referrer_policy = | |
| 1059 ProcessReferrerPolicyHeaderOnRedirect(request_, &referrer_source); | |
| 1060 } else { | |
| 1061 referrer_source = request_->referrer(); | |
| 1062 redirect_info.new_referrer_policy = request_->referrer_policy(); | |
| 1063 } | |
| 1064 | |
| 947 // Alter the referrer if redirecting cross-origin (especially HTTP->HTTPS). | 1065 // Alter the referrer if redirecting cross-origin (especially HTTP->HTTPS). |
| 948 redirect_info.new_referrer = | 1066 redirect_info.new_referrer = |
| 949 ComputeReferrerForRedirect(request_->referrer_policy(), | 1067 ComputeReferrerForRedirect(redirect_info.new_referrer_policy, |
| 950 request_->referrer(), | 1068 referrer_source, redirect_info.new_url) |
| 951 redirect_info.new_url).spec(); | 1069 .spec(); |
| 952 | 1070 |
| 953 std::string include_referer; | 1071 std::string include_referer; |
| 954 request_->GetResponseHeaderByName("include-referer-token-binding-id", | 1072 request_->GetResponseHeaderByName("include-referer-token-binding-id", |
| 955 &include_referer); | 1073 &include_referer); |
| 956 if (include_referer == "true" && | 1074 if (include_referer == "true" && |
| 957 request_->ssl_info().token_binding_negotiated) { | 1075 request_->ssl_info().token_binding_negotiated) { |
| 958 redirect_info.referred_token_binding_host = url.host(); | 1076 redirect_info.referred_token_binding_host = url.host(); |
| 959 } | 1077 } |
| 960 | 1078 |
| 961 return redirect_info; | 1079 return redirect_info; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 978 int64_t total_sent_bytes = GetTotalSentBytes(); | 1096 int64_t total_sent_bytes = GetTotalSentBytes(); |
| 979 DCHECK_GE(total_sent_bytes, last_notified_total_sent_bytes_); | 1097 DCHECK_GE(total_sent_bytes, last_notified_total_sent_bytes_); |
| 980 if (total_sent_bytes > last_notified_total_sent_bytes_) { | 1098 if (total_sent_bytes > last_notified_total_sent_bytes_) { |
| 981 network_delegate_->NotifyNetworkBytesSent( | 1099 network_delegate_->NotifyNetworkBytesSent( |
| 982 request_, total_sent_bytes - last_notified_total_sent_bytes_); | 1100 request_, total_sent_bytes - last_notified_total_sent_bytes_); |
| 983 } | 1101 } |
| 984 last_notified_total_sent_bytes_ = total_sent_bytes; | 1102 last_notified_total_sent_bytes_ = total_sent_bytes; |
| 985 } | 1103 } |
| 986 | 1104 |
| 987 } // namespace net | 1105 } // namespace net |
| OLD | NEW |