url_request.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 3// found in the LICENSE file. 4 5#include "net/url_request/url_request.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/callback.h" 10#include "base/compiler_specific.h" 11#include "base/debug/stack_trace.h" 12#include "base/lazy_instance.h" 13#include "base/memory/singleton.h" 14#include "base/message_loop.h" 15#include "base/metrics/stats_counters.h" 16#include "base/stl_util.h" 17#include "base/synchronization/lock.h" 18#include "net/base/auth.h" 19#include "net/base/host_port_pair.h" 20#include "net/base/load_flags.h" 21#include "net/base/net_errors.h" 22#include "net/base/net_log.h" 23#include "net/base/network_change_notifier.h" 24#include "net/base/network_delegate.h" 25#include "net/base/ssl_cert_request_info.h" 26#include "net/base/upload_data.h" 27#include "net/http/http_response_headers.h" 28#include "net/http/http_util.h" 29#include "net/url_request/url_request_context.h" 30#include "net/url_request/url_request_error_job.h" 31#include "net/url_request/url_request_job.h" 32#include "net/url_request/url_request_job_manager.h" 33#include "net/url_request/url_request_netlog_params.h" 34#include "net/url_request/url_request_redirect_job.h" 35 36using base::Time; 37using std::string; 38 39namespace net { 40 41namespace { 42 43// Max number of http redirects to follow. Same number as gecko. 44const int kMaxRedirects = 20; 45 46// Discard headers which have meaning in POST (Content-Length, Content-Type, 47// Origin). 48void StripPostSpecificHeaders(HttpRequestHeaders* headers) { 49 // These are headers that may be attached to a POST. 50 headers->RemoveHeader(HttpRequestHeaders::kContentLength); 51 headers->RemoveHeader(HttpRequestHeaders::kContentType); 52 headers->RemoveHeader(HttpRequestHeaders::kOrigin); 53} 54 55// TODO(battre): Delete this, see http://crbug.com/89321: 56// This counter keeps track of the identifiers used for URL requests so far. 57// 0 is reserved to represent an invalid ID. 58uint64 g_next_url_request_identifier = 1; 59 60// This lock protects g_next_url_request_identifier. 61base::LazyInstance<base::Lock>::Leaky 62 g_next_url_request_identifier_lock = LAZY_INSTANCE_INITIALIZER; 63 64// Returns an prior unused identifier for URL requests. 65uint64 GenerateURLRequestIdentifier() { 66 base::AutoLock lock(g_next_url_request_identifier_lock.Get()); 67 return g_next_url_request_identifier++; 68} 69 70// True once the first URLRequest was started. 71bool g_url_requests_started = false; 72 73// True if cookies are accepted by default. 74bool g_default_can_use_cookies = true; 75 76} // namespace 77 78URLRequest::ProtocolFactory* 79URLRequest::Deprecated::RegisterProtocolFactory(const std::string& scheme, 80 ProtocolFactory* factory) { 81 return URLRequest::RegisterProtocolFactory(scheme, factory); 82} 83 84void URLRequest::Deprecated::RegisterRequestInterceptor( 85 Interceptor* interceptor) { 86 URLRequest::RegisterRequestInterceptor(interceptor); 87} 88 89void URLRequest::Deprecated::UnregisterRequestInterceptor( 90 Interceptor* interceptor) { 91 URLRequest::UnregisterRequestInterceptor(interceptor); 92} 93 94/////////////////////////////////////////////////////////////////////////////// 95// URLRequest::Interceptor 96 97URLRequestJob* URLRequest::Interceptor::MaybeInterceptRedirect( 98 URLRequest* request, 99 NetworkDelegate* network_delegate, 100 const GURL& location) { 101 return NULL; 102} 103 104URLRequestJob* URLRequest::Interceptor::MaybeInterceptResponse( 105 URLRequest* request, NetworkDelegate* network_delegate) { 106 return NULL; 107} 108 109/////////////////////////////////////////////////////////////////////////////// 110// URLRequest::Delegate 111 112void URLRequest::Delegate::OnReceivedRedirect(URLRequest* request, 113 const GURL& new_url, 114 bool* defer_redirect) { 115} 116 117void URLRequest::Delegate::OnAuthRequired(URLRequest* request, 118 AuthChallengeInfo* auth_info) { 119 request->CancelAuth(); 120} 121 122void URLRequest::Delegate::OnCertificateRequested( 123 URLRequest* request, 124 SSLCertRequestInfo* cert_request_info) { 125 request->Cancel(); 126} 127 128void URLRequest::Delegate::OnSSLCertificateError(URLRequest* request, 129 const SSLInfo& ssl_info, 130 bool is_hsts_ok) { 131 request->Cancel(); 132} 133 134/////////////////////////////////////////////////////////////////////////////// 135// URLRequest 136 137// TODO(shalev): Get rid of this constructor in favour of the one below it. 138URLRequest::URLRequest(const GURL& url, 139 Delegate* delegate, 140 const URLRequestContext* context) 141 : context_(context), 142 network_delegate_(context->network_delegate()), 143 net_log_(BoundNetLog::Make(context->net_log(), 144 NetLog::SOURCE_URL_REQUEST)), 145 url_chain_(1, url), 146 method_("GET"), 147 referrer_policy_(CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE), 148 load_flags_(LOAD_NORMAL), 149 delegate_(delegate), 150 is_pending_(false), 151 is_redirecting_(false), 152 redirect_limit_(kMaxRedirects), 153 priority_(LOWEST), 154 identifier_(GenerateURLRequestIdentifier()), 155 blocked_on_delegate_(false), 156 ALLOW_THIS_IN_INITIALIZER_LIST(before_request_callback_( 157 base::Bind(&URLRequest::BeforeRequestComplete, 158 base::Unretained(this)))), 159 has_notified_completion_(false), 160 received_response_content_length_(0), 161 creation_time_(base::TimeTicks::Now()) { 162 SIMPLE_STATS_COUNTER("URLRequestCount"); 163 164 // Sanity check out environment. 165 DCHECK(MessageLoop::current()) << "The current MessageLoop must exist"; 166 167 DCHECK(MessageLoop::current()->IsType(MessageLoop::TYPE_IO)) << "" 168 "The current MessageLoop must be TYPE_IO"; 169 170 CHECK(context); 171 context->url_requests()->insert(this); 172 173 net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE); 174} 175 176URLRequest::URLRequest(const GURL& url, 177 Delegate* delegate, 178 const URLRequestContext* context, 179 NetworkDelegate* network_delegate) 180 : context_(context), 181 network_delegate_(network_delegate), 182 net_log_(BoundNetLog::Make(context->net_log(), 183 NetLog::SOURCE_URL_REQUEST)), 184 url_chain_(1, url), 185 method_("GET"), 186 referrer_policy_(CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE), 187 load_flags_(LOAD_NORMAL), 188 delegate_(delegate), 189 is_pending_(false), 190 is_redirecting_(false), 191 redirect_limit_(kMaxRedirects), 192 priority_(LOWEST), 193 identifier_(GenerateURLRequestIdentifier()), 194 blocked_on_delegate_(false), 195 ALLOW_THIS_IN_INITIALIZER_LIST(before_request_callback_( 196 base::Bind(&URLRequest::BeforeRequestComplete, 197 base::Unretained(this)))), 198 has_notified_completion_(false), 199 received_response_content_length_(0), 200 creation_time_(base::TimeTicks::Now()) { 201 SIMPLE_STATS_COUNTER("URLRequestCount"); 202 203 // Sanity check out environment. 204 DCHECK(MessageLoop::current()) << "The current MessageLoop must exist"; 205 206 DCHECK(MessageLoop::current()->IsType(MessageLoop::TYPE_IO)) << "" 207 "The current MessageLoop must be TYPE_IO"; 208 209 CHECK(context); 210 context->url_requests()->insert(this); 211 212 net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE); 213} 214 215URLRequest::~URLRequest() { 216 Cancel(); 217 218 if (network_delegate_) { 219 network_delegate_->NotifyURLRequestDestroyed(this); 220 if (job_) 221 job_->NotifyURLRequestDestroyed(); 222 } 223 224 if (job_) 225 OrphanJob(); 226 227 int deleted = context_->url_requests()->erase(this); 228 CHECK_EQ(1, deleted); 229 230 int net_error = OK; 231 // Log error only on failure, not cancellation, as even successful requests 232 // are "cancelled" on destruction. 233 if (status_.status() == URLRequestStatus::FAILED) 234 net_error = status_.error(); 235 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_REQUEST_ALIVE, net_error); 236} 237 238// static 239URLRequest::ProtocolFactory* URLRequest::RegisterProtocolFactory( 240 const string& scheme, ProtocolFactory* factory) { 241 return URLRequestJobManager::GetInstance()->RegisterProtocolFactory(scheme, 242 factory); 243} 244 245// static 246void URLRequest::RegisterRequestInterceptor(Interceptor* interceptor) { 247 URLRequestJobManager::GetInstance()->RegisterRequestInterceptor(interceptor); 248} 249 250// static 251void URLRequest::UnregisterRequestInterceptor(Interceptor* interceptor) { 252 URLRequestJobManager::GetInstance()->UnregisterRequestInterceptor( 253 interceptor); 254} 255 256void URLRequest::AppendBytesToUpload(const char* bytes, int bytes_len) { 257 DCHECK(bytes_len > 0 && bytes); 258 if (!upload_) 259 upload_ = new UploadData(); 260 upload_->AppendBytes(bytes, bytes_len); 261} 262 263void URLRequest::EnableChunkedUpload() { 264 DCHECK(!upload_ || upload_->is_chunked()); 265 if (!upload_) { 266 upload_ = new UploadData(); 267 upload_->set_is_chunked(true); 268 } 269} 270 271void URLRequest::AppendChunkToUpload(const char* bytes, 272 int bytes_len, 273 bool is_last_chunk) { 274 DCHECK(upload_); 275 DCHECK(upload_->is_chunked()); 276 DCHECK_GT(bytes_len, 0); 277 upload_->AppendChunk(bytes, bytes_len, is_last_chunk); 278} 279 280void URLRequest::set_upload(UploadData* upload) { 281 upload_ = upload; 282} 283 284// Get the upload data directly. 285const UploadData* URLRequest::get_upload() const { 286 return upload_.get(); 287} 288 289UploadData* URLRequest::get_upload_mutable() { 290 return upload_.get(); 291} 292 293bool URLRequest::has_upload() const { 294 return upload_ != NULL; 295} 296 297void URLRequest::SetExtraRequestHeaderById(int id, const string& value, 298 bool overwrite) { 299 DCHECK(!is_pending_ || is_redirecting_); 300 NOTREACHED() << "implement me!"; 301} 302 303void URLRequest::SetExtraRequestHeaderByName(const string& name, 304 const string& value, 305 bool overwrite) { 306 DCHECK(!is_pending_ || is_redirecting_); 307 if (overwrite) { 308 extra_request_headers_.SetHeader(name, value); 309 } else { 310 extra_request_headers_.SetHeaderIfMissing(name, value); 311 } 312} 313 314void URLRequest::SetExtraRequestHeaders( 315 const HttpRequestHeaders& headers) { 316 DCHECK(!is_pending_); 317 extra_request_headers_ = headers; 318 319 // NOTE: This method will likely become non-trivial once the other setters 320 // for request headers are implemented. 321} 322 323LoadStateWithParam URLRequest::GetLoadState() const { 324 if (blocked_on_delegate_) { 325 return LoadStateWithParam(LOAD_STATE_WAITING_FOR_DELEGATE, 326 load_state_param_); 327 } 328 return LoadStateWithParam(job_ ? job_->GetLoadState() : LOAD_STATE_IDLE, 329 string16()); 330} 331 332UploadProgress URLRequest::GetUploadProgress() const { 333 if (!job_) { 334 // We haven't started or the request was cancelled 335 return UploadProgress(); 336 } 337 if (final_upload_progress_.position()) { 338 // The first job completed and none of the subsequent series of 339 // GETs when following redirects will upload anything, so we return the 340 // cached results from the initial job, the POST. 341 return final_upload_progress_; 342 } 343 return job_->GetUploadProgress(); 344} 345 346void URLRequest::GetResponseHeaderById(int id, string* value) { 347 DCHECK(job_); 348 NOTREACHED() << "implement me!"; 349} 350 351void URLRequest::GetResponseHeaderByName(const string& name, string* value) { 352 DCHECK(value); 353 if (response_info_.headers) { 354 response_info_.headers->GetNormalizedHeader(name, value); 355 } else { 356 value->clear(); 357 } 358} 359 360void URLRequest::GetAllResponseHeaders(string* headers) { 361 DCHECK(headers); 362 if (response_info_.headers) { 363 response_info_.headers->GetNormalizedHeaders(headers); 364 } else { 365 headers->clear(); 366 } 367} 368 369HostPortPair URLRequest::GetSocketAddress() const { 370 DCHECK(job_); 371 return job_->GetSocketAddress(); 372} 373 374HttpResponseHeaders* URLRequest::response_headers() const { 375 return response_info_.headers.get(); 376} 377 378bool URLRequest::GetResponseCookies(ResponseCookies* cookies) { 379 DCHECK(job_); 380 return job_->GetResponseCookies(cookies); 381} 382 383void URLRequest::GetMimeType(string* mime_type) { 384 DCHECK(job_); 385 job_->GetMimeType(mime_type); 386} 387 388void URLRequest::GetCharset(string* charset) { 389 DCHECK(job_); 390 job_->GetCharset(charset); 391} 392 393int URLRequest::GetResponseCode() { 394 DCHECK(job_); 395 return job_->GetResponseCode(); 396} 397 398// static 399void URLRequest::SetDefaultCookiePolicyToBlock() { 400 CHECK(!g_url_requests_started); 401 g_default_can_use_cookies = false; 402} 403 404// static 405bool URLRequest::IsHandledProtocol(const std::string& scheme) { 406 return URLRequestJobManager::GetInstance()->SupportsScheme(scheme); 407} 408 409// static 410bool URLRequest::IsHandledURL(const GURL& url) { 411 if (!url.is_valid()) { 412 // We handle error cases. 413 return true; 414 } 415 416 return IsHandledProtocol(url.scheme()); 417} 418 419void URLRequest::set_first_party_for_cookies( 420 const GURL& first_party_for_cookies) { 421 first_party_for_cookies_ = first_party_for_cookies; 422} 423 424void URLRequest::set_method(const std::string& method) { 425 DCHECK(!is_pending_); 426 method_ = method; 427} 428 429void URLRequest::set_referrer(const std::string& referrer) { 430 DCHECK(!is_pending_); 431 referrer_ = referrer; 432} 433 434GURL URLRequest::GetSanitizedReferrer() const { 435 GURL ret(referrer()); 436 437 // Ensure that we do not send username and password fields in the referrer. 438 if (ret.has_username() || ret.has_password()) { 439 GURL::Replacements referrer_mods; 440 referrer_mods.ClearUsername(); 441 referrer_mods.ClearPassword(); 442 ret = ret.ReplaceComponents(referrer_mods); 443 } 444 445 return ret; 446} 447 448void URLRequest::set_referrer_policy(ReferrerPolicy referrer_policy) { 449 DCHECK(!is_pending_); 450 referrer_policy_ = referrer_policy; 451} 452 453void URLRequest::set_delegate(Delegate* delegate) { 454 delegate_ = delegate; 455} 456 457void URLRequest::Start() { 458 DCHECK_EQ(network_delegate_, context_->network_delegate()); 459 460 g_url_requests_started = true; 461 response_info_.request_time = Time::Now(); 462 463 // Only notify the delegate for the initial request. 464 if (network_delegate_) { 465 int error = network_delegate_->NotifyBeforeURLRequest( 466 this, before_request_callback_, &delegate_redirect_url_); 467 if (error == net::ERR_IO_PENDING) { 468 // Paused on the delegate, will invoke |before_request_callback_| later. 469 SetBlockedOnDelegate(); 470 } else { 471 BeforeRequestComplete(error); 472 } 473 return; 474 } 475 476 StartJob(URLRequestJobManager::GetInstance()->CreateJob( 477 this, network_delegate_)); 478} 479 480/////////////////////////////////////////////////////////////////////////////// 481 482void URLRequest::BeforeRequestComplete(int error) { 483 DCHECK(!job_); 484 DCHECK_NE(ERR_IO_PENDING, error); 485 DCHECK_EQ(network_delegate_, context_->network_delegate()); 486 487 // Check that there are no callbacks to already canceled requests. 488 DCHECK_NE(URLRequestStatus::CANCELED, status_.status()); 489 490 if (blocked_on_delegate_) 491 SetUnblockedOnDelegate(); 492 493 if (error != OK) { 494 std::string source("delegate"); 495 net_log_.AddEvent(NetLog::TYPE_CANCELLED, 496 NetLog::StringCallback("source", &source)); 497 StartJob(new URLRequestErrorJob(this, network_delegate_, error)); 498 } else if (!delegate_redirect_url_.is_empty()) { 499 GURL new_url; 500 new_url.Swap(&delegate_redirect_url_); 501 502 URLRequestRedirectJob* job = new URLRequestRedirectJob( 503 this, network_delegate_, new_url); 504 // Use status code 307 to preserve the method, so POST requests work. 505 job->set_redirect_code( 506 URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT); 507 StartJob(job); 508 } else { 509 StartJob(URLRequestJobManager::GetInstance()->CreateJob( 510 this, network_delegate_)); 511 } 512} 513 514void URLRequest::StartJob(URLRequestJob* job) { 515 DCHECK(!is_pending_); 516 DCHECK(!job_); 517 518 net_log_.BeginEvent( 519 NetLog::TYPE_URL_REQUEST_START_JOB, 520 base::Bind(&NetLogURLRequestStartCallback, 521 &url(), &method_, load_flags_, priority_, 522 upload_.get() ? upload_->identifier() : -1)); 523 524 job_ = job; 525 job_->SetExtraRequestHeaders(extra_request_headers_); 526 527 if (upload_.get()) 528 job_->SetUpload(upload_.get()); 529 530 is_pending_ = true; 531 is_redirecting_ = false; 532 533 response_info_.was_cached = false; 534 535 // Don't allow errors to be sent from within Start(). 536 // TODO(brettw) this may cause NotifyDone to be sent synchronously, 537 // we probably don't want this: they should be sent asynchronously so 538 // the caller does not get reentered. 539 job_->Start(); 540} 541 542void URLRequest::Restart() { 543 // Should only be called if the original job didn't make any progress. 544 DCHECK(job_ && !job_->has_response_started()); 545 RestartWithJob(URLRequestJobManager::GetInstance()->CreateJob( 546 this, network_delegate_)); 547} 548 549void URLRequest::RestartWithJob(URLRequestJob *job) { 550 DCHECK(job->request() == this); 551 PrepareToRestart(); 552 StartJob(job); 553} 554 555void URLRequest::Cancel() { 556 DoCancel(ERR_ABORTED, SSLInfo()); 557} 558 559void URLRequest::CancelWithError(int error) { 560 DoCancel(error, SSLInfo()); 561} 562 563void URLRequest::CancelWithSSLError(int error, const SSLInfo& ssl_info) { 564 // This should only be called on a started request. 565 if (!is_pending_ || !job_ || job_->has_response_started()) { 566 NOTREACHED(); 567 return; 568 } 569 DoCancel(error, ssl_info); 570} 571 572void URLRequest::DoCancel(int error, const SSLInfo& ssl_info) { 573 DCHECK(error < 0); 574 575 // If the URL request already has an error status, then canceling is a no-op. 576 // Plus, we don't want to change the error status once it has been set. 577 if (status_.is_success()) { 578 status_.set_status(URLRequestStatus::CANCELED); 579 status_.set_error(error); 580 response_info_.ssl_info = ssl_info; 581 582 // If the request hasn't already been completed, log a cancellation event. 583 if (!has_notified_completion_) { 584 // Don't log an error code on ERR_ABORTED, since that's redundant. 585 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_CANCELLED, 586 error == ERR_ABORTED ? OK : error); 587 } 588 } 589 590 if (is_pending_ && job_) 591 job_->Kill(); 592 593 // We need to notify about the end of this job here synchronously. The 594 // Job sends an asynchronous notification but by the time this is processed, 595 // our |context_| is NULL. 596 NotifyRequestCompleted(); 597 598 // The Job will call our NotifyDone method asynchronously. This is done so 599 // that the Delegate implementation can call Cancel without having to worry 600 // about being called recursively. 601} 602 603bool URLRequest::Read(IOBuffer* dest, int dest_size, int* bytes_read) { 604 DCHECK(job_); 605 DCHECK(bytes_read); 606 *bytes_read = 0; 607 608 // This handles a cancel that happens while paused. 609 // TODO(ahendrickson): DCHECK() that it is not done after 610 // http://crbug.com/115705 is fixed. 611 if (job_->is_done()) 612 return false; 613 614 if (dest_size == 0) { 615 // Caller is not too bright. I guess we've done what they asked. 616 return true; 617 } 618 619 // Once the request fails or is cancelled, read will just return 0 bytes 620 // to indicate end of stream. 621 if (!status_.is_success()) { 622 return true; 623 } 624 625 bool rv = job_->Read(dest, dest_size, bytes_read); 626 // If rv is false, the status cannot be success. 627 DCHECK(rv || status_.status() != URLRequestStatus::SUCCESS); 628 if (rv && *bytes_read <= 0 && status_.is_success()) 629 NotifyRequestCompleted(); 630 return rv; 631} 632 633void URLRequest::StopCaching() { 634 DCHECK(job_); 635 job_->StopCaching(); 636} 637 638void URLRequest::NotifyReceivedRedirect(const GURL& location, 639 bool* defer_redirect) { 640 is_redirecting_ = true; 641 642 URLRequestJob* job = 643 URLRequestJobManager::GetInstance()->MaybeInterceptRedirect( 644 this, network_delegate_, location); 645 if (job) { 646 RestartWithJob(job); 647 } else if (delegate_) { 648 delegate_->OnReceivedRedirect(this, location, defer_redirect); 649 } 650} 651 652void URLRequest::NotifyResponseStarted() { 653 int net_error = OK; 654 if (!status_.is_success()) 655 net_error = status_.error(); 656 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_URL_REQUEST_START_JOB, 657 net_error); 658 659 URLRequestJob* job = 660 URLRequestJobManager::GetInstance()->MaybeInterceptResponse( 661 this, network_delegate_); 662 if (job) { 663 RestartWithJob(job); 664 } else { 665 if (delegate_) { 666 // In some cases (e.g. an event was canceled), we might have sent the 667 // completion event and receive a NotifyResponseStarted() later. 668 if (!has_notified_completion_ && status_.is_success()) { 669 if (network_delegate_) 670 network_delegate_->NotifyResponseStarted(this); 671 } 672 673 // Notify in case the entire URL Request has been finished. 674 if (!has_notified_completion_ && !status_.is_success()) 675 NotifyRequestCompleted(); 676 677 delegate_->OnResponseStarted(this); 678 // Nothing may appear below this line as OnResponseStarted may delete 679 // |this|. 680 } 681 } 682} 683 684void URLRequest::FollowDeferredRedirect() { 685 CHECK(job_); 686 CHECK(status_.is_success()); 687 688 job_->FollowDeferredRedirect(); 689} 690 691void URLRequest::SetAuth(const AuthCredentials& credentials) { 692 DCHECK(job_); 693 DCHECK(job_->NeedsAuth()); 694 695 job_->SetAuth(credentials); 696} 697 698void URLRequest::CancelAuth() { 699 DCHECK(job_); 700 DCHECK(job_->NeedsAuth()); 701 702 job_->CancelAuth(); 703} 704 705void URLRequest::ContinueWithCertificate(X509Certificate* client_cert) { 706 DCHECK(job_); 707 708 job_->ContinueWithCertificate(client_cert); 709} 710 711void URLRequest::ContinueDespiteLastError() { 712 DCHECK(job_); 713 714 job_->ContinueDespiteLastError(); 715} 716 717void URLRequest::PrepareToRestart() { 718 DCHECK(job_); 719 720 // Close the current URL_REQUEST_START_JOB, since we will be starting a new 721 // one. 722 net_log_.EndEvent(NetLog::TYPE_URL_REQUEST_START_JOB); 723 724 OrphanJob(); 725 726 response_info_ = HttpResponseInfo(); 727 response_info_.request_time = Time::Now(); 728 status_ = URLRequestStatus(); 729 is_pending_ = false; 730} 731 732void URLRequest::OrphanJob() { 733 // When calling this function, please check that URLRequestHttpJob is 734 // not in between calling NetworkDelegate::NotifyHeadersReceived receiving 735 // the call back. This is currently guaranteed by the following strategies: 736 // - OrphanJob is called on JobRestart, in this case the URLRequestJob cannot 737 // be receiving any headers at that time. 738 // - OrphanJob is called in ~URLRequest, in this case 739 // NetworkDelegate::NotifyURLRequestDestroyed notifies the NetworkDelegate 740 // that the callback becomes invalid. 741 job_->Kill(); 742 job_->DetachRequest(); // ensures that the job will not call us again 743 job_ = NULL; 744} 745 746int URLRequest::Redirect(const GURL& location, int http_status_code) { 747 if (net_log_.IsLoggingAllEvents()) { 748 net_log_.AddEvent( 749 NetLog::TYPE_URL_REQUEST_REDIRECTED, 750 NetLog::StringCallback("location", &location.possibly_invalid_spec())); 751 } 752 753 if (network_delegate_) 754 network_delegate_->NotifyBeforeRedirect(this, location); 755 756 if (redirect_limit_ <= 0) { 757 DVLOG(1) << "disallowing redirect: exceeds limit"; 758 return ERR_TOO_MANY_REDIRECTS; 759 } 760 761 if (!location.is_valid()) 762 return ERR_INVALID_URL; 763 764 if (!job_->IsSafeRedirect(location)) { 765 DVLOG(1) << "disallowing redirect: unsafe protocol"; 766 return ERR_UNSAFE_REDIRECT; 767 } 768 769 // For 303 redirects, all request methods except HEAD are converted to GET, 770 // as per the latest httpbis draft. The draft also allows POST requests to 771 // be converted to GETs when following 301/302 redirects, for historical 772 // reasons. Most major browsers do this and so shall we. Both RFC 2616 and 773 // the httpbis draft say to prompt the user to confirm the generation of new 774 // requests, other than GET and HEAD requests, but IE omits these prompts and 775 // so shall we. 776 // See: https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-17#section-7.3 777 bool was_post = method_ == "POST"; 778 if ((http_status_code == 303 && method_ != "HEAD") || 779 ((http_status_code == 301 || http_status_code == 302) && was_post)) { 780 method_ = "GET"; 781 upload_ = NULL; 782 if (was_post) { 783 // If being switched from POST to GET, must remove headers that were 784 // specific to the POST and don't have meaning in GET. For example 785 // the inclusion of a multipart Content-Type header in GET can cause 786 // problems with some servers: 787 // http://code.google.com/p/chromium/issues/detail?id=843 788 StripPostSpecificHeaders(&extra_request_headers_); 789 } 790 } 791 792 // Suppress the referrer if we're redirecting out of https. 793 if (referrer_policy_ == 794 CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE && 795 GURL(referrer_).SchemeIsSecure() && !location.SchemeIsSecure()) { 796 referrer_.clear(); 797 } 798 799 url_chain_.push_back(location); 800 --redirect_limit_; 801 802 if (!final_upload_progress_.position()) 803 final_upload_progress_ = job_->GetUploadProgress(); 804 805 PrepareToRestart(); 806 Start(); 807 return OK; 808} 809 810const URLRequestContext* URLRequest::context() const { 811 return context_; 812} 813 814int64 URLRequest::GetExpectedContentSize() const { 815 int64 expected_content_size = -1; 816 if (job_) 817 expected_content_size = job_->expected_content_size(); 818 819 return expected_content_size; 820} 821 822bool URLRequest::GetHSTSRedirect(GURL* redirect_url) const { 823 const GURL& url = this->url(); 824 if (!url.SchemeIs("http")) 825 return false; 826 TransportSecurityState::DomainState domain_state; 827 if (context()->transport_security_state() && 828 context()->transport_security_state()->GetDomainState( 829 url.host(), 830 SSLConfigService::IsSNIAvailable(context()->ssl_config_service()), 831 &domain_state) && 832 domain_state.ShouldRedirectHTTPToHTTPS()) { 833 url_canon::Replacements<char> replacements; 834 const char kNewScheme[] = "https"; 835 replacements.SetScheme(kNewScheme, 836 url_parse::Component(0, strlen(kNewScheme))); 837 *redirect_url = url.ReplaceComponents(replacements); 838 return true; 839 } 840 return false; 841} 842 843void URLRequest::NotifyAuthRequired(AuthChallengeInfo* auth_info) { 844 NetworkDelegate::AuthRequiredResponse rv = 845 NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION; 846 auth_info_ = auth_info; 847 if (network_delegate_) { 848 rv = network_delegate_->NotifyAuthRequired( 849 this, 850 *auth_info, 851 base::Bind(&URLRequest::NotifyAuthRequiredComplete, 852 base::Unretained(this)), 853 &auth_credentials_); 854 } 855 856 if (rv == NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING) { 857 SetBlockedOnDelegate(); 858 } else { 859 NotifyAuthRequiredComplete(rv); 860 } 861} 862 863void URLRequest::NotifyAuthRequiredComplete( 864 NetworkDelegate::AuthRequiredResponse result) { 865 SetUnblockedOnDelegate(); 866 867 // Check that there are no callbacks to already canceled requests. 868 DCHECK_NE(URLRequestStatus::CANCELED, status_.status()); 869 870 // NotifyAuthRequired may be called multiple times, such as 871 // when an authentication attempt fails. Clear out the data 872 // so it can be reset on another round. 873 AuthCredentials credentials = auth_credentials_; 874 auth_credentials_ = AuthCredentials(); 875 scoped_refptr<AuthChallengeInfo> auth_info; 876 auth_info.swap(auth_info_); 877 878 switch (result) { 879 case NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION: 880 // Defer to the URLRequest::Delegate, since the NetworkDelegate 881 // didn't take an action. 882 if (delegate_) 883 delegate_->OnAuthRequired(this, auth_info.get()); 884 break; 885 886 case NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH: 887 SetAuth(credentials); 888 break; 889 890 case NetworkDelegate::AUTH_REQUIRED_RESPONSE_CANCEL_AUTH: 891 CancelAuth(); 892 break; 893 894 case NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING: 895 NOTREACHED(); 896 break; 897 } 898} 899 900void URLRequest::NotifyCertificateRequested( 901 SSLCertRequestInfo* cert_request_info) { 902 if (delegate_) 903 delegate_->OnCertificateRequested(this, cert_request_info); 904} 905 906void URLRequest::NotifySSLCertificateError(const SSLInfo& ssl_info, 907 bool fatal) { 908 if (delegate_) 909 delegate_->OnSSLCertificateError(this, ssl_info, fatal); 910} 911 912bool URLRequest::CanGetCookies(const CookieList& cookie_list) const { 913 DCHECK(!(load_flags_ & LOAD_DO_NOT_SEND_COOKIES)); 914 if (network_delegate_) { 915 return network_delegate_->CanGetCookies(*this, cookie_list); 916 } 917 return g_default_can_use_cookies; 918} 919 920bool URLRequest::CanSetCookie(const std::string& cookie_line, 921 CookieOptions* options) const { 922 DCHECK(!(load_flags_ & LOAD_DO_NOT_SAVE_COOKIES)); 923 if (network_delegate_) { 924 return network_delegate_->CanSetCookie(*this, cookie_line, options); 925 } 926 return g_default_can_use_cookies; 927} 928 929 930void URLRequest::NotifyReadCompleted(int bytes_read) { 931 // Notify in case the entire URL Request has been finished. 932 if (bytes_read <= 0) 933 NotifyRequestCompleted(); 934 935 // Notify NetworkChangeNotifier that we just received network data. 936 // This is to identify cases where the NetworkChangeNotifier thinks we 937 // are off-line but we are still receiving network data (crbug.com/124069). 938 if (bytes_read > 0 && !was_cached()) 939 NetworkChangeNotifier::NotifyDataReceived(url()); 940 941 if (delegate_) 942 delegate_->OnReadCompleted(this, bytes_read); 943 944 // Nothing below this line as OnReadCompleted may delete |this|. 945} 946 947void URLRequest::NotifyRequestCompleted() { 948 // TODO(battre): Get rid of this check, according to willchan it should 949 // not be needed. 950 if (has_notified_completion_) 951 return; 952 953 is_pending_ = false; 954 is_redirecting_ = false; 955 has_notified_completion_ = true; 956 if (network_delegate_) 957 network_delegate_->NotifyCompleted(this, job_ != NULL); 958} 959 960void URLRequest::SetBlockedOnDelegate() { 961 blocked_on_delegate_ = true; 962 net_log_.BeginEvent(NetLog::TYPE_URL_REQUEST_BLOCKED_ON_DELEGATE); 963} 964 965void URLRequest::SetUnblockedOnDelegate() { 966 if (!blocked_on_delegate_) 967 return; 968 blocked_on_delegate_ = false; 969 load_state_param_.clear(); 970 net_log_.EndEvent(NetLog::TYPE_URL_REQUEST_BLOCKED_ON_DELEGATE); 971} 972 973void URLRequest::set_stack_trace(const base::debug::StackTrace& stack_trace) { 974 base::debug::StackTrace* stack_trace_copy = 975 new base::debug::StackTrace(NULL, 0); 976 *stack_trace_copy = stack_trace; 977 stack_trace_.reset(stack_trace_copy); 978} 979 980const base::debug::StackTrace* URLRequest::stack_trace() const { 981 return stack_trace_.get(); 982} 983 984} // namespace net 985