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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/power_monitor/power_monitor.h" | 10 #include "base/power_monitor/power_monitor.h" |
(...skipping 15 matching lines...) Expand all Loading... | |
26 NetworkDelegate* network_delegate) | 26 NetworkDelegate* network_delegate) |
27 : request_(request), | 27 : request_(request), |
28 done_(false), | 28 done_(false), |
29 prefilter_bytes_read_(0), | 29 prefilter_bytes_read_(0), |
30 postfilter_bytes_read_(0), | 30 postfilter_bytes_read_(0), |
31 filter_input_byte_count_(0), | 31 filter_input_byte_count_(0), |
32 filter_needs_more_output_space_(false), | 32 filter_needs_more_output_space_(false), |
33 filtered_read_buffer_len_(0), | 33 filtered_read_buffer_len_(0), |
34 has_handled_response_(false), | 34 has_handled_response_(false), |
35 expected_content_size_(-1), | 35 expected_content_size_(-1), |
36 deferred_redirect_status_code_(-1), | |
37 network_delegate_(network_delegate), | 36 network_delegate_(network_delegate), |
38 weak_factory_(this) { | 37 weak_factory_(this) { |
39 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); | 38 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); |
40 if (power_monitor) | 39 if (power_monitor) |
41 power_monitor->AddObserver(this); | 40 power_monitor->AddObserver(this); |
42 } | 41 } |
43 | 42 |
44 void URLRequestJob::SetUpload(UploadDataStream* upload) { | 43 void URLRequestJob::SetUpload(UploadDataStream* upload) { |
45 } | 44 } |
46 | 45 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
196 } | 195 } |
197 | 196 |
198 void URLRequestJob::ContinueDespiteLastError() { | 197 void URLRequestJob::ContinueDespiteLastError() { |
199 // Implementations should know how to recover from errors they generate. | 198 // Implementations should know how to recover from errors they generate. |
200 // If this code was reached, we are trying to recover from an error that | 199 // If this code was reached, we are trying to recover from an error that |
201 // we don't know how to recover from. | 200 // we don't know how to recover from. |
202 NOTREACHED(); | 201 NOTREACHED(); |
203 } | 202 } |
204 | 203 |
205 void URLRequestJob::FollowDeferredRedirect() { | 204 void URLRequestJob::FollowDeferredRedirect() { |
206 DCHECK(deferred_redirect_status_code_ != -1); | 205 DCHECK_NE(-1, deferred_redirect_info_.status_code); |
207 | 206 |
208 // NOTE: deferred_redirect_url_ may be invalid, and attempting to redirect to | 207 // NOTE: deferred_redirect_info_ may be invalid, and attempting to follow it |
209 // such an URL will fail inside FollowRedirect. The DCHECK above asserts | 208 // will fail inside FollowRedirect. The DCHECK above asserts that we called |
210 // that we called OnReceivedRedirect. | 209 // OnReceivedRedirect. |
211 | 210 |
212 // It is also possible that FollowRedirect will drop the last reference to | 211 // It is also possible that FollowRedirect will drop the last reference to |
213 // this job, so we need to reset our members before calling it. | 212 // this job, so we need to reset our members before calling it. |
214 | 213 |
215 GURL redirect_url = deferred_redirect_url_; | 214 RedirectInfo redirect_info = deferred_redirect_info_; |
216 int redirect_status_code = deferred_redirect_status_code_; | 215 deferred_redirect_info_ = RedirectInfo(); |
217 | 216 FollowRedirect(redirect_info); |
218 deferred_redirect_url_ = GURL(); | |
219 deferred_redirect_status_code_ = -1; | |
220 | |
221 FollowRedirect(redirect_url, redirect_status_code); | |
222 } | 217 } |
223 | 218 |
224 void URLRequestJob::ResumeNetworkStart() { | 219 void URLRequestJob::ResumeNetworkStart() { |
225 // This should only be called for HTTP Jobs, and implemented in the derived | 220 // This should only be called for HTTP Jobs, and implemented in the derived |
226 // class. | 221 // class. |
227 NOTREACHED(); | 222 NOTREACHED(); |
228 } | 223 } |
229 | 224 |
230 bool URLRequestJob::GetMimeType(std::string* mime_type) const { | 225 bool URLRequestJob::GetMimeType(std::string* mime_type) const { |
231 return false; | 226 return false; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
328 if (request_) | 323 if (request_) |
329 request_->OnHeadersComplete(); | 324 request_->OnHeadersComplete(); |
330 | 325 |
331 GURL new_location; | 326 GURL new_location; |
332 int http_status_code; | 327 int http_status_code; |
333 if (IsRedirectResponse(&new_location, &http_status_code)) { | 328 if (IsRedirectResponse(&new_location, &http_status_code)) { |
334 // Redirect response bodies are not read. Notify the transaction | 329 // Redirect response bodies are not read. Notify the transaction |
335 // so it does not treat being stopped as an error. | 330 // so it does not treat being stopped as an error. |
336 DoneReadingRedirectResponse(); | 331 DoneReadingRedirectResponse(); |
337 | 332 |
338 const GURL& url = request_->url(); | 333 RedirectInfo redirect_info = |
339 | 334 ComputeRedirectInfo(new_location, http_status_code); |
340 // Move the reference fragment of the old location to the new one if the | |
341 // new one has none. This duplicates mozilla's behavior. | |
342 if (url.is_valid() && url.has_ref() && !new_location.has_ref() && | |
343 CopyFragmentOnRedirect(new_location)) { | |
344 GURL::Replacements replacements; | |
345 // Reference the |ref| directly out of the original URL to avoid a | |
346 // malloc. | |
347 replacements.SetRef(url.spec().data(), | |
348 url.parsed_for_possibly_invalid_spec().ref); | |
349 new_location = new_location.ReplaceComponents(replacements); | |
350 } | |
351 | 335 |
352 bool defer_redirect = false; | 336 bool defer_redirect = false; |
353 request_->NotifyReceivedRedirect(new_location, &defer_redirect); | 337 request_->NotifyReceivedRedirect(redirect_info, &defer_redirect); |
354 | 338 |
355 // Ensure that the request wasn't detached or destroyed in | 339 // Ensure that the request wasn't detached or destroyed in |
356 // NotifyReceivedRedirect | 340 // NotifyReceivedRedirect |
357 if (!request_ || !request_->has_delegate()) | 341 if (!request_ || !request_->has_delegate()) |
358 return; | 342 return; |
359 | 343 |
360 // If we were not cancelled, then maybe follow the redirect. | 344 // If we were not cancelled, then maybe follow the redirect. |
361 if (request_->status().is_success()) { | 345 if (request_->status().is_success()) { |
362 if (defer_redirect) { | 346 if (defer_redirect) { |
363 deferred_redirect_url_ = new_location; | 347 deferred_redirect_info_ = redirect_info; |
364 deferred_redirect_status_code_ = http_status_code; | |
365 } else { | 348 } else { |
366 FollowRedirect(new_location, http_status_code); | 349 FollowRedirect(redirect_info); |
367 } | 350 } |
368 return; | 351 return; |
369 } | 352 } |
370 } else if (NeedsAuth()) { | 353 } else if (NeedsAuth()) { |
371 scoped_refptr<AuthChallengeInfo> auth_info; | 354 scoped_refptr<AuthChallengeInfo> auth_info; |
372 GetAuthChallengeInfo(&auth_info); | 355 GetAuthChallengeInfo(&auth_info); |
373 // Need to check for a NULL auth_info because the server may have failed | 356 // Need to check for a NULL auth_info because the server may have failed |
374 // to send a challenge with the 401 response. | 357 // to send a challenge with the 401 response. |
375 if (auth_info.get()) { | 358 if (auth_info.get()) { |
376 request_->NotifyAuthRequired(auth_info.get()); | 359 request_->NotifyAuthRequired(auth_info.get()); |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
719 | 702 |
720 if (!request_->status().is_io_pending()) { | 703 if (!request_->status().is_io_pending()) { |
721 // If the read completes synchronously, either success or failure, | 704 // If the read completes synchronously, either success or failure, |
722 // invoke the OnRawReadComplete callback so we can account for the | 705 // invoke the OnRawReadComplete callback so we can account for the |
723 // completed read. | 706 // completed read. |
724 OnRawReadComplete(*bytes_read); | 707 OnRawReadComplete(*bytes_read); |
725 } | 708 } |
726 return rv; | 709 return rv; |
727 } | 710 } |
728 | 711 |
729 void URLRequestJob::FollowRedirect(const GURL& location, int http_status_code) { | 712 void URLRequestJob::FollowRedirect(const RedirectInfo& redirect_info) { |
730 int rv = request_->Redirect(location, http_status_code); | 713 int rv = request_->Redirect(redirect_info); |
731 if (rv != OK) | 714 if (rv != OK) |
732 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); | 715 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); |
733 } | 716 } |
734 | 717 |
735 void URLRequestJob::OnRawReadComplete(int bytes_read) { | 718 void URLRequestJob::OnRawReadComplete(int bytes_read) { |
736 DCHECK(raw_read_buffer_.get()); | 719 DCHECK(raw_read_buffer_.get()); |
737 // If |filter_| is non-NULL, bytes will be logged after it is applied instead. | 720 // If |filter_| is non-NULL, bytes will be logged after it is applied instead. |
738 if (!filter_.get() && request() && request()->net_log().IsLoggingBytes() && | 721 if (!filter_.get() && request() && request()->net_log().IsLoggingBytes() && |
739 bytes_read > 0) { | 722 bytes_read > 0) { |
740 request()->net_log().AddByteTransferEvent( | 723 request()->net_log().AddByteTransferEvent( |
(...skipping 22 matching lines...) Expand all Loading... | |
763 network_delegate_->NotifyRawBytesRead(*request_, bytes_read); | 746 network_delegate_->NotifyRawBytesRead(*request_, bytes_read); |
764 } | 747 } |
765 | 748 |
766 bool URLRequestJob::FilterHasData() { | 749 bool URLRequestJob::FilterHasData() { |
767 return filter_.get() && filter_->stream_data_len(); | 750 return filter_.get() && filter_->stream_data_len(); |
768 } | 751 } |
769 | 752 |
770 void URLRequestJob::UpdatePacketReadTimes() { | 753 void URLRequestJob::UpdatePacketReadTimes() { |
771 } | 754 } |
772 | 755 |
756 RedirectInfo URLRequestJob::ComputeRedirectInfo(const GURL& location, | |
757 int http_status_code) { | |
758 const GURL& url = request_->url(); | |
759 | |
760 // Move the reference fragment of the old location to the new one if the | |
761 // new one has none. This duplicates mozilla's behavior. | |
762 GURL new_location = location; | |
763 if (url.is_valid() && url.has_ref() && !new_location.has_ref() && | |
764 CopyFragmentOnRedirect(new_location)) { | |
765 GURL::Replacements replacements; | |
766 // Reference the |ref| directly out of the original URL to avoid a | |
767 // malloc. | |
768 replacements.SetRef(url.spec().data(), | |
769 url.parsed_for_possibly_invalid_spec().ref); | |
770 new_location = new_location.ReplaceComponents(replacements); | |
771 } | |
772 | |
773 RedirectInfo redirect_info; | |
774 | |
775 redirect_info.status_code = http_status_code; | |
776 | |
777 // The request method may change, depending on the status code. | |
778 redirect_info.method = URLRequest::ComputeMethodForRedirect( | |
779 request_->method(), http_status_code); | |
780 | |
781 redirect_info.url = new_location; | |
mmenke
2014/07/17 16:55:09
Could avoid this copy by getting rid of new_locati
davidben
2014/07/17 22:03:55
Done.
| |
782 | |
783 // Update the first-party URL if appropriate. | |
784 if (request_->first_party_url_policy() == | |
785 URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT) { | |
mmenke
2014/07/17 16:55:09
Sure there are integration tests for this (At leas
davidben
2014/07/17 22:03:55
Done.
| |
786 redirect_info.first_party_for_cookies = new_location; | |
787 } else { | |
788 redirect_info.first_party_for_cookies = request_->first_party_for_cookies(); | |
789 } | |
790 | |
791 // Suppress the referrer if we're redirecting out of https. | |
792 if (request_->referrer_policy() == | |
793 URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE && | |
794 GURL(request_->referrer()).SchemeIsSecure() && | |
795 !new_location.SchemeIsSecure()) { | |
796 redirect_info.referrer.clear(); | |
797 } else { | |
798 redirect_info.referrer = request_->referrer(); | |
799 } | |
800 | |
801 return redirect_info; | |
802 } | |
803 | |
773 } // namespace net | 804 } // namespace net |
OLD | NEW |