| 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 RedirectInfo redirect_info; |
| 761 |
| 762 redirect_info.status_code = http_status_code; |
| 763 |
| 764 // The request method may change, depending on the status code. |
| 765 redirect_info.new_method = URLRequest::ComputeMethodForRedirect( |
| 766 request_->method(), http_status_code); |
| 767 |
| 768 // Move the reference fragment of the old location to the new one if the |
| 769 // new one has none. This duplicates mozilla's behavior. |
| 770 if (url.is_valid() && url.has_ref() && !location.has_ref() && |
| 771 CopyFragmentOnRedirect(location)) { |
| 772 GURL::Replacements replacements; |
| 773 // Reference the |ref| directly out of the original URL to avoid a |
| 774 // malloc. |
| 775 replacements.SetRef(url.spec().data(), |
| 776 url.parsed_for_possibly_invalid_spec().ref); |
| 777 redirect_info.new_url = location.ReplaceComponents(replacements); |
| 778 } else { |
| 779 redirect_info.new_url = location; |
| 780 } |
| 781 |
| 782 // Update the first-party URL if appropriate. |
| 783 if (request_->first_party_url_policy() == |
| 784 URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT) { |
| 785 redirect_info.new_first_party_for_cookies = redirect_info.new_url; |
| 786 } else { |
| 787 redirect_info.new_first_party_for_cookies = |
| 788 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 !redirect_info.new_url.SchemeIsSecure()) { |
| 796 redirect_info.new_referrer.clear(); |
| 797 } else { |
| 798 redirect_info.new_referrer = request_->referrer(); |
| 799 } |
| 800 |
| 801 return redirect_info; |
| 802 } |
| 803 |
| 773 } // namespace net | 804 } // namespace net |
| OLD | NEW |