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 request->referrer_policy() to the appropriate | |
69 // URLRequest::ReferrerPolicy, and sets |new_referrer_source| to the | |
70 // value that 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 // This function does not modify |request| or |new_referrer_source| if | |
75 // |token| does not match any policy. | |
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* request, | |
84 std::string* new_referrer_source) { | |
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 request->set_referrer_policy(URLRequest::NEVER_CLEAR_REFERRER); | |
estark
2016/06/25 14:42:15
Hrm. These set_referrer_policy() calls run afoul o
| |
92 *new_referrer_source = std::string(); | |
93 return; | |
94 } | |
95 | |
96 // For a referrer policy of 'no-referrer-when-downgrade', setting the | |
97 // URLRequest's ReferrerPolicy is sufficient; | |
98 // ComputeReferrerForRedirect() will apply this policy to strip the | |
99 // referrer if necessary. | |
100 if (base::CompareCaseInsensitiveASCII(token, "default") == 0 || | |
101 base::CompareCaseInsensitiveASCII(token, "no-referrer-when-downgrade") == | |
102 0) { | |
103 request->set_referrer_policy( | |
104 URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE); | |
105 *new_referrer_source = referrer_source; | |
106 return; | |
107 } | |
108 | |
109 // For a referrer policy of 'origin', strip the referrer source to the | |
110 // origin. After doing so, there is no need to modify the referrer | |
111 // further, so set the policy to leave the referrer alone. | |
112 if (base::CompareCaseInsensitiveASCII(token, "origin") == 0) { | |
113 request->set_referrer_policy(URLRequest::NEVER_CLEAR_REFERRER); | |
114 *new_referrer_source = GURL(referrer_source).GetOrigin().spec(); | |
115 return; | |
116 } | |
117 | |
118 // For a referrer policy of 'origin-when-cross-origin', setting the | |
119 // URLRequest's ReferrerPolicy is sufficient; | |
120 // ComputeReferrerForRedirect() will apply this policy to strip the | |
121 // referrer if necessary. | |
122 if (base::CompareCaseInsensitiveASCII(token, "origin-when-cross-origin") == | |
123 0) { | |
124 request->set_referrer_policy( | |
125 URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN); | |
126 *new_referrer_source = referrer_source; | |
127 return; | |
128 } | |
129 | |
130 // For a referrer policy of 'unsafe-url', leave the referrer source | |
131 // untouched and set the policy so that ComputeReferrerForRedirect() | |
132 // will not modify it. | |
133 if (base::CompareCaseInsensitiveASCII(token, "always") == 0 || | |
134 base::CompareCaseInsensitiveASCII(token, "unsafe-url") == 0) { | |
135 request->set_referrer_policy(URLRequest::NEVER_CLEAR_REFERRER); | |
136 *new_referrer_source = referrer_source; | |
137 return; | |
138 } | |
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 present. If the | |
144 // header parses to a valid policy, |request|'s referrer policy will be | |
145 // updated if necessary, and |new_referrer_source| will be set to the | |
146 // URL that should be used as what the spec calls the "referrerSource" | |
147 // -- that is, the referrer that will be used as input to | |
148 // ComputeReferrerForRedirect(). | |
149 void ProcessReferrerPolicyHeaderOnRedirect(URLRequest* request, | |
150 const std::string& referrer_source, | |
151 std::string* new_referrer_source) { | |
152 std::string referrer_policy_header; | |
153 request->GetResponseHeaderByName("Referrer-Policy", &referrer_policy_header); | |
154 std::vector<std::string> policy_tokens = | |
155 base::SplitString(referrer_policy_header, ",", base::TRIM_WHITESPACE, | |
156 base::SPLIT_WANT_NONEMPTY); | |
157 *new_referrer_source = referrer_source; | |
158 for (const auto& token : policy_tokens) { | |
159 GetReferrerPolicyFromToken(token, referrer_source, request, | |
160 new_referrer_source); | |
161 } | |
162 } | |
163 | |
65 } // namespace | 164 } // namespace |
66 | 165 |
67 URLRequestJob::URLRequestJob(URLRequest* request, | 166 URLRequestJob::URLRequestJob(URLRequest* request, |
68 NetworkDelegate* network_delegate) | 167 NetworkDelegate* network_delegate) |
69 : request_(request), | 168 : request_(request), |
70 done_(false), | 169 done_(false), |
71 prefilter_bytes_read_(0), | 170 prefilter_bytes_read_(0), |
72 postfilter_bytes_read_(0), | 171 postfilter_bytes_read_(0), |
73 filter_needs_more_output_space_(false), | 172 filter_needs_more_output_space_(false), |
74 filtered_read_buffer_len_(0), | 173 filtered_read_buffer_len_(0), |
(...skipping 316 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 | 490 // the time stamps if it has that information. The default request_time is |
392 // set by URLRequest before it calls our Start method. | 491 // set by URLRequest before it calls our Start method. |
393 request_->response_info_.response_time = base::Time::Now(); | 492 request_->response_info_.response_time = base::Time::Now(); |
394 GetResponseInfo(&request_->response_info_); | 493 GetResponseInfo(&request_->response_info_); |
395 | 494 |
396 MaybeNotifyNetworkBytes(); | 495 MaybeNotifyNetworkBytes(); |
397 request_->OnHeadersComplete(); | 496 request_->OnHeadersComplete(); |
398 | 497 |
399 GURL new_location; | 498 GURL new_location; |
400 int http_status_code; | 499 int http_status_code; |
500 | |
401 if (IsRedirectResponse(&new_location, &http_status_code)) { | 501 if (IsRedirectResponse(&new_location, &http_status_code)) { |
402 // Redirect response bodies are not read. Notify the transaction | 502 // Redirect response bodies are not read. Notify the transaction |
403 // so it does not treat being stopped as an error. | 503 // so it does not treat being stopped as an error. |
404 DoneReadingRedirectResponse(); | 504 DoneReadingRedirectResponse(); |
405 | 505 |
406 // When notifying the URLRequest::Delegate, it can destroy the request, | 506 // When notifying the URLRequest::Delegate, it can destroy the request, |
407 // which will destroy |this|. After calling to the URLRequest::Delegate, | 507 // 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 | 508 // pointer must be checked to see if |this| still exists, and if not, the |
409 // code must return immediately. | 509 // code must return immediately. |
410 base::WeakPtr<URLRequestJob> weak_this(weak_factory_.GetWeakPtr()); | 510 base::WeakPtr<URLRequestJob> weak_this(weak_factory_.GetWeakPtr()); |
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
937 | 1037 |
938 // Update the first-party URL if appropriate. | 1038 // Update the first-party URL if appropriate. |
939 if (request_->first_party_url_policy() == | 1039 if (request_->first_party_url_policy() == |
940 URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT) { | 1040 URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT) { |
941 redirect_info.new_first_party_for_cookies = redirect_info.new_url; | 1041 redirect_info.new_first_party_for_cookies = redirect_info.new_url; |
942 } else { | 1042 } else { |
943 redirect_info.new_first_party_for_cookies = | 1043 redirect_info.new_first_party_for_cookies = |
944 request_->first_party_for_cookies(); | 1044 request_->first_party_for_cookies(); |
945 } | 1045 } |
946 | 1046 |
1047 // |referrer_source| is the starting-point referrer, which may be | |
1048 // modified by ComputeReferrerForRedirect() to produce a new referrer | |
1049 // that obeys the request's referrer policy. | |
1050 std::string referrer_source; | |
1051 if (request_->context()->enable_referrer_policy_header()) { | |
1052 ProcessReferrerPolicyHeaderOnRedirect(request_, request_->referrer(), | |
1053 &referrer_source); | |
1054 } else { | |
1055 referrer_source = request_->referrer(); | |
1056 } | |
1057 | |
947 // Alter the referrer if redirecting cross-origin (especially HTTP->HTTPS). | 1058 // Alter the referrer if redirecting cross-origin (especially HTTP->HTTPS). |
948 redirect_info.new_referrer = | 1059 redirect_info.new_referrer = |
949 ComputeReferrerForRedirect(request_->referrer_policy(), | 1060 ComputeReferrerForRedirect(request_->referrer_policy(), referrer_source, |
950 request_->referrer(), | 1061 redirect_info.new_url) |
951 redirect_info.new_url).spec(); | 1062 .spec(); |
952 | 1063 |
953 std::string include_referer; | 1064 std::string include_referer; |
954 request_->GetResponseHeaderByName("include-referer-token-binding-id", | 1065 request_->GetResponseHeaderByName("include-referer-token-binding-id", |
955 &include_referer); | 1066 &include_referer); |
956 if (include_referer == "true" && | 1067 if (include_referer == "true" && |
957 request_->ssl_info().token_binding_negotiated) { | 1068 request_->ssl_info().token_binding_negotiated) { |
958 redirect_info.referred_token_binding_host = url.host(); | 1069 redirect_info.referred_token_binding_host = url.host(); |
959 } | 1070 } |
960 | 1071 |
961 return redirect_info; | 1072 return redirect_info; |
(...skipping 16 matching lines...) Expand all Loading... | |
978 int64_t total_sent_bytes = GetTotalSentBytes(); | 1089 int64_t total_sent_bytes = GetTotalSentBytes(); |
979 DCHECK_GE(total_sent_bytes, last_notified_total_sent_bytes_); | 1090 DCHECK_GE(total_sent_bytes, last_notified_total_sent_bytes_); |
980 if (total_sent_bytes > last_notified_total_sent_bytes_) { | 1091 if (total_sent_bytes > last_notified_total_sent_bytes_) { |
981 network_delegate_->NotifyNetworkBytesSent( | 1092 network_delegate_->NotifyNetworkBytesSent( |
982 request_, total_sent_bytes - last_notified_total_sent_bytes_); | 1093 request_, total_sent_bytes - last_notified_total_sent_bytes_); |
983 } | 1094 } |
984 last_notified_total_sent_bytes_ = total_sent_bytes; | 1095 last_notified_total_sent_bytes_ = total_sent_bytes; |
985 } | 1096 } |
986 | 1097 |
987 } // namespace net | 1098 } // namespace net |
OLD | NEW |