url_request.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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/message_loop.h" 15#include "base/metrics/histogram.h" 16#include "base/metrics/stats_counters.h" 17#include "base/metrics/user_metrics.h" 18#include "base/stl_util.h" 19#include "base/strings/utf_string_conversions.h" 20#include "base/synchronization/lock.h" 21#include "base/values.h" 22#include "net/base/auth.h" 23#include "net/base/host_port_pair.h" 24#include "net/base/load_flags.h" 25#include "net/base/load_timing_info.h" 26#include "net/base/net_errors.h" 27#include "net/base/net_log.h" 28#include "net/base/network_change_notifier.h" 29#include "net/base/network_delegate.h" 30#include "net/base/upload_data_stream.h" 31#include "net/http/http_response_headers.h" 32#include "net/http/http_util.h" 33#include "net/ssl/ssl_cert_request_info.h" 34#include "net/url_request/url_request_context.h" 35#include "net/url_request/url_request_error_job.h" 36#include "net/url_request/url_request_job.h" 37#include "net/url_request/url_request_job_manager.h" 38#include "net/url_request/url_request_netlog_params.h" 39#include "net/url_request/url_request_redirect_job.h" 40 41using base::Time; 42using std::string; 43 44namespace net { 45 46namespace { 47 48// Max number of http redirects to follow. Same number as gecko. 49const int kMaxRedirects = 20; 50 51// Discard headers which have meaning in POST (Content-Length, Content-Type, 52// Origin). 53void StripPostSpecificHeaders(HttpRequestHeaders* headers) { 54 // These are headers that may be attached to a POST. 55 headers->RemoveHeader(HttpRequestHeaders::kContentLength); 56 headers->RemoveHeader(HttpRequestHeaders::kContentType); 57 headers->RemoveHeader(HttpRequestHeaders::kOrigin); 58} 59 60// TODO(battre): Delete this, see http://crbug.com/89321: 61// This counter keeps track of the identifiers used for URL requests so far. 62// 0 is reserved to represent an invalid ID. 63uint64 g_next_url_request_identifier = 1; 64 65// This lock protects g_next_url_request_identifier. 66base::LazyInstance<base::Lock>::Leaky 67 g_next_url_request_identifier_lock = LAZY_INSTANCE_INITIALIZER; 68 69// Returns an prior unused identifier for URL requests. 70uint64 GenerateURLRequestIdentifier() { 71 base::AutoLock lock(g_next_url_request_identifier_lock.Get()); 72 return g_next_url_request_identifier++; 73} 74 75// True once the first URLRequest was started. 76bool g_url_requests_started = false; 77 78// True if cookies are accepted by default. 79bool g_default_can_use_cookies = true; 80 81// When the URLRequest first assempts load timing information, it has the times 82// at which each event occurred. The API requires the time which the request 83// was blocked on each phase. This function handles the conversion. 84// 85// In the case of reusing a SPDY session, old proxy results may have been 86// reused, so proxy resolution times may be before the request was started. 87// 88// Due to preconnect and late binding, it is also possible for the connection 89// attempt to start before a request has been started, or proxy resolution 90// completed. 91// 92// This functions fixes both those cases. 93void ConvertRealLoadTimesToBlockingTimes( 94 net::LoadTimingInfo* load_timing_info) { 95 DCHECK(!load_timing_info->request_start.is_null()); 96 97 // Earliest time possible for the request to be blocking on connect events. 98 base::TimeTicks block_on_connect = load_timing_info->request_start; 99 100 if (!load_timing_info->proxy_resolve_start.is_null()) { 101 DCHECK(!load_timing_info->proxy_resolve_end.is_null()); 102 103 // Make sure the proxy times are after request start. 104 if (load_timing_info->proxy_resolve_start < load_timing_info->request_start) 105 load_timing_info->proxy_resolve_start = load_timing_info->request_start; 106 if (load_timing_info->proxy_resolve_end < load_timing_info->request_start) 107 load_timing_info->proxy_resolve_end = load_timing_info->request_start; 108 109 // Connect times must also be after the proxy times. 110 block_on_connect = load_timing_info->proxy_resolve_end; 111 } 112 113 // Make sure connection times are after start and proxy times. 114 115 net::LoadTimingInfo::ConnectTiming* connect_timing = 116 &load_timing_info->connect_timing; 117 if (!connect_timing->dns_start.is_null()) { 118 DCHECK(!connect_timing->dns_end.is_null()); 119 if (connect_timing->dns_start < block_on_connect) 120 connect_timing->dns_start = block_on_connect; 121 if (connect_timing->dns_end < block_on_connect) 122 connect_timing->dns_end = block_on_connect; 123 } 124 125 if (!connect_timing->connect_start.is_null()) { 126 DCHECK(!connect_timing->connect_end.is_null()); 127 if (connect_timing->connect_start < block_on_connect) 128 connect_timing->connect_start = block_on_connect; 129 if (connect_timing->connect_end < block_on_connect) 130 connect_timing->connect_end = block_on_connect; 131 } 132 133 if (!connect_timing->ssl_start.is_null()) { 134 DCHECK(!connect_timing->ssl_end.is_null()); 135 if (connect_timing->ssl_start < block_on_connect) 136 connect_timing->ssl_start = block_on_connect; 137 if (connect_timing->ssl_end < block_on_connect) 138 connect_timing->ssl_end = block_on_connect; 139 } 140} 141 142} // namespace 143 144URLRequest::ProtocolFactory* 145URLRequest::Deprecated::RegisterProtocolFactory(const std::string& scheme, 146 ProtocolFactory* factory) { 147 return URLRequest::RegisterProtocolFactory(scheme, factory); 148} 149 150void URLRequest::Deprecated::RegisterRequestInterceptor( 151 Interceptor* interceptor) { 152 URLRequest::RegisterRequestInterceptor(interceptor); 153} 154 155void URLRequest::Deprecated::UnregisterRequestInterceptor( 156 Interceptor* interceptor) { 157 URLRequest::UnregisterRequestInterceptor(interceptor); 158} 159 160/////////////////////////////////////////////////////////////////////////////// 161// URLRequest::Interceptor 162 163URLRequestJob* URLRequest::Interceptor::MaybeInterceptRedirect( 164 URLRequest* request, 165 NetworkDelegate* network_delegate, 166 const GURL& location) { 167 return NULL; 168} 169 170URLRequestJob* URLRequest::Interceptor::MaybeInterceptResponse( 171 URLRequest* request, NetworkDelegate* network_delegate) { 172 return NULL; 173} 174 175/////////////////////////////////////////////////////////////////////////////// 176// URLRequest::Delegate 177 178void URLRequest::Delegate::OnReceivedRedirect(URLRequest* request, 179 const GURL& new_url, 180 bool* defer_redirect) { 181} 182 183void URLRequest::Delegate::OnAuthRequired(URLRequest* request, 184 AuthChallengeInfo* auth_info) { 185 request->CancelAuth(); 186} 187 188void URLRequest::Delegate::OnCertificateRequested( 189 URLRequest* request, 190 SSLCertRequestInfo* cert_request_info) { 191 request->Cancel(); 192} 193 194void URLRequest::Delegate::OnSSLCertificateError(URLRequest* request, 195 const SSLInfo& ssl_info, 196 bool is_hsts_ok) { 197 request->Cancel(); 198} 199 200void URLRequest::Delegate::OnBeforeNetworkStart(URLRequest* request, 201 bool* defer) { 202} 203 204/////////////////////////////////////////////////////////////////////////////// 205// URLRequest 206 207URLRequest::URLRequest(const GURL& url, 208 RequestPriority priority, 209 Delegate* delegate, 210 const URLRequestContext* context) 211 : identifier_(GenerateURLRequestIdentifier()) { 212 Init(url, priority, delegate, context, NULL); 213} 214 215URLRequest::URLRequest(const GURL& url, 216 RequestPriority priority, 217 Delegate* delegate, 218 const URLRequestContext* context, 219 CookieStore* cookie_store) 220 : identifier_(GenerateURLRequestIdentifier()) { 221 Init(url, priority, delegate, context, cookie_store); 222} 223 224URLRequest::~URLRequest() { 225 Cancel(); 226 227 if (network_delegate_) { 228 network_delegate_->NotifyURLRequestDestroyed(this); 229 if (job_.get()) 230 job_->NotifyURLRequestDestroyed(); 231 } 232 233 if (job_.get()) 234 OrphanJob(); 235 236 int deleted = context_->url_requests()->erase(this); 237 CHECK_EQ(1, deleted); 238 239 int net_error = OK; 240 // Log error only on failure, not cancellation, as even successful requests 241 // are "cancelled" on destruction. 242 if (status_.status() == URLRequestStatus::FAILED) 243 net_error = status_.error(); 244 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_REQUEST_ALIVE, net_error); 245} 246 247// static 248URLRequest::ProtocolFactory* URLRequest::RegisterProtocolFactory( 249 const string& scheme, ProtocolFactory* factory) { 250 return URLRequestJobManager::GetInstance()->RegisterProtocolFactory(scheme, 251 factory); 252} 253 254// static 255void URLRequest::RegisterRequestInterceptor(Interceptor* interceptor) { 256 URLRequestJobManager::GetInstance()->RegisterRequestInterceptor(interceptor); 257} 258 259// static 260void URLRequest::UnregisterRequestInterceptor(Interceptor* interceptor) { 261 URLRequestJobManager::GetInstance()->UnregisterRequestInterceptor( 262 interceptor); 263} 264 265void URLRequest::Init(const GURL& url, 266 RequestPriority priority, 267 Delegate* delegate, 268 const URLRequestContext* context, 269 CookieStore* cookie_store) { 270 context_ = context; 271 network_delegate_ = context->network_delegate(); 272 net_log_ = BoundNetLog::Make(context->net_log(), NetLog::SOURCE_URL_REQUEST); 273 url_chain_.push_back(url); 274 method_ = "GET"; 275 referrer_policy_ = CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE; 276 load_flags_ = LOAD_NORMAL; 277 delegate_ = delegate; 278 is_pending_ = false; 279 is_redirecting_ = false; 280 redirect_limit_ = kMaxRedirects; 281 priority_ = priority; 282 calling_delegate_ = false; 283 use_blocked_by_as_load_param_ =false; 284 before_request_callback_ = base::Bind(&URLRequest::BeforeRequestComplete, 285 base::Unretained(this)); 286 has_notified_completion_ = false; 287 received_response_content_length_ = 0; 288 creation_time_ = base::TimeTicks::Now(); 289 notified_before_network_start_ = false; 290 291 SIMPLE_STATS_COUNTER("URLRequestCount"); 292 293 // Sanity check out environment. 294 DCHECK(base::MessageLoop::current()) 295 << "The current base::MessageLoop must exist"; 296 297 CHECK(context); 298 context->url_requests()->insert(this); 299 cookie_store_ = cookie_store; 300 if (cookie_store_ == NULL) 301 cookie_store_ = context->cookie_store(); 302 303 net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE); 304} 305 306void URLRequest::EnableChunkedUpload() { 307 DCHECK(!upload_data_stream_ || upload_data_stream_->is_chunked()); 308 if (!upload_data_stream_) { 309 upload_data_stream_.reset( 310 new UploadDataStream(UploadDataStream::CHUNKED, 0)); 311 } 312} 313 314void URLRequest::AppendChunkToUpload(const char* bytes, 315 int bytes_len, 316 bool is_last_chunk) { 317 DCHECK(upload_data_stream_); 318 DCHECK(upload_data_stream_->is_chunked()); 319 DCHECK_GT(bytes_len, 0); 320 upload_data_stream_->AppendChunk(bytes, bytes_len, is_last_chunk); 321} 322 323void URLRequest::set_upload(scoped_ptr<UploadDataStream> upload) { 324 DCHECK(!upload->is_chunked()); 325 upload_data_stream_ = upload.Pass(); 326} 327 328const UploadDataStream* URLRequest::get_upload() const { 329 return upload_data_stream_.get(); 330} 331 332bool URLRequest::has_upload() const { 333 return upload_data_stream_.get() != NULL; 334} 335 336void URLRequest::SetExtraRequestHeaderById(int id, const string& value, 337 bool overwrite) { 338 DCHECK(!is_pending_ || is_redirecting_); 339 NOTREACHED() << "implement me!"; 340} 341 342void URLRequest::SetExtraRequestHeaderByName(const string& name, 343 const string& value, 344 bool overwrite) { 345 DCHECK(!is_pending_ || is_redirecting_); 346 if (overwrite) { 347 extra_request_headers_.SetHeader(name, value); 348 } else { 349 extra_request_headers_.SetHeaderIfMissing(name, value); 350 } 351} 352 353void URLRequest::RemoveRequestHeaderByName(const string& name) { 354 DCHECK(!is_pending_ || is_redirecting_); 355 extra_request_headers_.RemoveHeader(name); 356} 357 358void URLRequest::SetExtraRequestHeaders( 359 const HttpRequestHeaders& headers) { 360 DCHECK(!is_pending_); 361 extra_request_headers_ = headers; 362 363 // NOTE: This method will likely become non-trivial once the other setters 364 // for request headers are implemented. 365} 366 367bool URLRequest::GetFullRequestHeaders(HttpRequestHeaders* headers) const { 368 if (!job_.get()) 369 return false; 370 371 return job_->GetFullRequestHeaders(headers); 372} 373 374int64 URLRequest::GetTotalReceivedBytes() const { 375 if (!job_.get()) 376 return 0; 377 378 return job_->GetTotalReceivedBytes(); 379} 380 381LoadStateWithParam URLRequest::GetLoadState() const { 382 // The !blocked_by_.empty() check allows |this| to report it's blocked on a 383 // delegate before it has been started. 384 if (calling_delegate_ || !blocked_by_.empty()) { 385 return LoadStateWithParam( 386 LOAD_STATE_WAITING_FOR_DELEGATE, 387 use_blocked_by_as_load_param_ ? base::UTF8ToUTF16(blocked_by_) : 388 base::string16()); 389 } 390 return LoadStateWithParam(job_.get() ? job_->GetLoadState() : LOAD_STATE_IDLE, 391 base::string16()); 392} 393 394base::Value* URLRequest::GetStateAsValue() const { 395 base::DictionaryValue* dict = new base::DictionaryValue(); 396 dict->SetString("url", original_url().possibly_invalid_spec()); 397 398 if (url_chain_.size() > 1) { 399 base::ListValue* list = new base::ListValue(); 400 for (std::vector<GURL>::const_iterator url = url_chain_.begin(); 401 url != url_chain_.end(); ++url) { 402 list->AppendString(url->possibly_invalid_spec()); 403 } 404 dict->Set("url_chain", list); 405 } 406 407 dict->SetInteger("load_flags", load_flags_); 408 409 LoadStateWithParam load_state = GetLoadState(); 410 dict->SetInteger("load_state", load_state.state); 411 if (!load_state.param.empty()) 412 dict->SetString("load_state_param", load_state.param); 413 if (!blocked_by_.empty()) 414 dict->SetString("delegate_info", blocked_by_); 415 416 dict->SetString("method", method_); 417 dict->SetBoolean("has_upload", has_upload()); 418 dict->SetBoolean("is_pending", is_pending_); 419 420 // Add the status of the request. The status should always be IO_PENDING, and 421 // the error should always be OK, unless something is holding onto a request 422 // that has finished or a request was leaked. Neither of these should happen. 423 switch (status_.status()) { 424 case URLRequestStatus::SUCCESS: 425 dict->SetString("status", "SUCCESS"); 426 break; 427 case URLRequestStatus::IO_PENDING: 428 dict->SetString("status", "IO_PENDING"); 429 break; 430 case URLRequestStatus::CANCELED: 431 dict->SetString("status", "CANCELED"); 432 break; 433 case URLRequestStatus::FAILED: 434 dict->SetString("status", "FAILED"); 435 break; 436 } 437 if (status_.error() != OK) 438 dict->SetInteger("net_error", status_.error()); 439 return dict; 440} 441 442void URLRequest::LogBlockedBy(const char* blocked_by) { 443 DCHECK(blocked_by); 444 DCHECK_GT(strlen(blocked_by), 0u); 445 446 // Only log information to NetLog during startup and certain deferring calls 447 // to delegates. For all reads but the first, do nothing. 448 if (!calling_delegate_ && !response_info_.request_time.is_null()) 449 return; 450 451 LogUnblocked(); 452 blocked_by_ = blocked_by; 453 use_blocked_by_as_load_param_ = false; 454 455 net_log_.BeginEvent( 456 NetLog::TYPE_DELEGATE_INFO, 457 NetLog::StringCallback("delegate_info", &blocked_by_)); 458} 459 460void URLRequest::LogAndReportBlockedBy(const char* source) { 461 LogBlockedBy(source); 462 use_blocked_by_as_load_param_ = true; 463} 464 465void URLRequest::LogUnblocked() { 466 if (blocked_by_.empty()) 467 return; 468 469 net_log_.EndEvent(NetLog::TYPE_DELEGATE_INFO); 470 blocked_by_.clear(); 471} 472 473UploadProgress URLRequest::GetUploadProgress() const { 474 if (!job_.get()) { 475 // We haven't started or the request was cancelled 476 return UploadProgress(); 477 } 478 if (final_upload_progress_.position()) { 479 // The first job completed and none of the subsequent series of 480 // GETs when following redirects will upload anything, so we return the 481 // cached results from the initial job, the POST. 482 return final_upload_progress_; 483 } 484 return job_->GetUploadProgress(); 485} 486 487void URLRequest::GetResponseHeaderById(int id, string* value) { 488 DCHECK(job_.get()); 489 NOTREACHED() << "implement me!"; 490} 491 492void URLRequest::GetResponseHeaderByName(const string& name, string* value) { 493 DCHECK(value); 494 if (response_info_.headers.get()) { 495 response_info_.headers->GetNormalizedHeader(name, value); 496 } else { 497 value->clear(); 498 } 499} 500 501void URLRequest::GetAllResponseHeaders(string* headers) { 502 DCHECK(headers); 503 if (response_info_.headers.get()) { 504 response_info_.headers->GetNormalizedHeaders(headers); 505 } else { 506 headers->clear(); 507 } 508} 509 510HostPortPair URLRequest::GetSocketAddress() const { 511 DCHECK(job_.get()); 512 return job_->GetSocketAddress(); 513} 514 515HttpResponseHeaders* URLRequest::response_headers() const { 516 return response_info_.headers.get(); 517} 518 519void URLRequest::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const { 520 *load_timing_info = load_timing_info_; 521} 522 523bool URLRequest::GetResponseCookies(ResponseCookies* cookies) { 524 DCHECK(job_.get()); 525 return job_->GetResponseCookies(cookies); 526} 527 528void URLRequest::GetMimeType(string* mime_type) { 529 DCHECK(job_.get()); 530 job_->GetMimeType(mime_type); 531} 532 533void URLRequest::GetCharset(string* charset) { 534 DCHECK(job_.get()); 535 job_->GetCharset(charset); 536} 537 538int URLRequest::GetResponseCode() const { 539 DCHECK(job_.get()); 540 return job_->GetResponseCode(); 541} 542 543void URLRequest::SetLoadFlags(int flags) { 544 if ((load_flags_ & LOAD_IGNORE_LIMITS) != (flags & LOAD_IGNORE_LIMITS)) { 545 DCHECK(!job_); 546 DCHECK(flags & LOAD_IGNORE_LIMITS); 547 DCHECK_EQ(priority_, MAXIMUM_PRIORITY); 548 } 549 load_flags_ = flags; 550 551 // This should be a no-op given the above DCHECKs, but do this 552 // anyway for release mode. 553 if ((load_flags_ & LOAD_IGNORE_LIMITS) != 0) 554 SetPriority(MAXIMUM_PRIORITY); 555} 556 557// static 558void URLRequest::SetDefaultCookiePolicyToBlock() { 559 CHECK(!g_url_requests_started); 560 g_default_can_use_cookies = false; 561} 562 563// static 564bool URLRequest::IsHandledProtocol(const std::string& scheme) { 565 return URLRequestJobManager::GetInstance()->SupportsScheme(scheme); 566} 567 568// static 569bool URLRequest::IsHandledURL(const GURL& url) { 570 if (!url.is_valid()) { 571 // We handle error cases. 572 return true; 573 } 574 575 return IsHandledProtocol(url.scheme()); 576} 577 578void URLRequest::set_first_party_for_cookies( 579 const GURL& first_party_for_cookies) { 580 first_party_for_cookies_ = first_party_for_cookies; 581} 582 583void URLRequest::set_method(const std::string& method) { 584 DCHECK(!is_pending_); 585 method_ = method; 586} 587 588// static 589std::string URLRequest::ComputeMethodForRedirect( 590 const std::string& method, 591 int http_status_code) { 592 // For 303 redirects, all request methods except HEAD are converted to GET, 593 // as per the latest httpbis draft. The draft also allows POST requests to 594 // be converted to GETs when following 301/302 redirects, for historical 595 // reasons. Most major browsers do this and so shall we. Both RFC 2616 and 596 // the httpbis draft say to prompt the user to confirm the generation of new 597 // requests, other than GET and HEAD requests, but IE omits these prompts and 598 // so shall we. 599 // See: https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-17#section-7.3 600 if ((http_status_code == 303 && method != "HEAD") || 601 ((http_status_code == 301 || http_status_code == 302) && 602 method == "POST")) { 603 return "GET"; 604 } 605 return method; 606} 607 608void URLRequest::SetReferrer(const std::string& referrer) { 609 DCHECK(!is_pending_); 610 GURL referrer_url(referrer); 611 UMA_HISTOGRAM_BOOLEAN("Net.URLRequest_SetReferrer_IsEmptyOrValid", 612 referrer_url.is_empty() || referrer_url.is_valid()); 613 if (referrer_url.is_valid()) { 614 referrer_ = referrer_url.GetAsReferrer().spec(); 615 } else { 616 referrer_ = referrer; 617 } 618} 619 620void URLRequest::set_referrer_policy(ReferrerPolicy referrer_policy) { 621 DCHECK(!is_pending_); 622 referrer_policy_ = referrer_policy; 623} 624 625void URLRequest::set_delegate(Delegate* delegate) { 626 delegate_ = delegate; 627} 628 629void URLRequest::Start() { 630 DCHECK_EQ(network_delegate_, context_->network_delegate()); 631 // Anything that sets |blocked_by_| before start should have cleaned up after 632 // itself. 633 DCHECK(blocked_by_.empty()); 634 635 g_url_requests_started = true; 636 response_info_.request_time = base::Time::Now(); 637 638 load_timing_info_ = LoadTimingInfo(); 639 load_timing_info_.request_start_time = response_info_.request_time; 640 load_timing_info_.request_start = base::TimeTicks::Now(); 641 642 // Only notify the delegate for the initial request. 643 if (network_delegate_) { 644 OnCallToDelegate(); 645 int error = network_delegate_->NotifyBeforeURLRequest( 646 this, before_request_callback_, &delegate_redirect_url_); 647 // If ERR_IO_PENDING is returned, the delegate will invoke 648 // |before_request_callback_| later. 649 if (error != ERR_IO_PENDING) 650 BeforeRequestComplete(error); 651 return; 652 } 653 654 StartJob(URLRequestJobManager::GetInstance()->CreateJob( 655 this, network_delegate_)); 656} 657 658/////////////////////////////////////////////////////////////////////////////// 659 660void URLRequest::BeforeRequestComplete(int error) { 661 DCHECK(!job_.get()); 662 DCHECK_NE(ERR_IO_PENDING, error); 663 DCHECK_EQ(network_delegate_, context_->network_delegate()); 664 665 // Check that there are no callbacks to already canceled requests. 666 DCHECK_NE(URLRequestStatus::CANCELED, status_.status()); 667 668 OnCallToDelegateComplete(); 669 670 if (error != OK) { 671 std::string source("delegate"); 672 net_log_.AddEvent(NetLog::TYPE_CANCELLED, 673 NetLog::StringCallback("source", &source)); 674 StartJob(new URLRequestErrorJob(this, network_delegate_, error)); 675 } else if (!delegate_redirect_url_.is_empty()) { 676 GURL new_url; 677 new_url.Swap(&delegate_redirect_url_); 678 679 URLRequestRedirectJob* job = new URLRequestRedirectJob( 680 this, network_delegate_, new_url, 681 // Use status code 307 to preserve the method, so POST requests work. 682 URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "Delegate"); 683 StartJob(job); 684 } else { 685 StartJob(URLRequestJobManager::GetInstance()->CreateJob( 686 this, network_delegate_)); 687 } 688} 689 690void URLRequest::StartJob(URLRequestJob* job) { 691 DCHECK(!is_pending_); 692 DCHECK(!job_.get()); 693 694 net_log_.BeginEvent( 695 NetLog::TYPE_URL_REQUEST_START_JOB, 696 base::Bind(&NetLogURLRequestStartCallback, 697 &url(), &method_, load_flags_, priority_, 698 upload_data_stream_ ? upload_data_stream_->identifier() : -1)); 699 700 job_ = job; 701 job_->SetExtraRequestHeaders(extra_request_headers_); 702 job_->SetPriority(priority_); 703 704 if (upload_data_stream_.get()) 705 job_->SetUpload(upload_data_stream_.get()); 706 707 is_pending_ = true; 708 is_redirecting_ = false; 709 710 response_info_.was_cached = false; 711 712 // If the referrer is secure, but the requested URL is not, the referrer 713 // policy should be something non-default. If you hit this, please file a 714 // bug. 715 if (referrer_policy_ == 716 CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE && 717 GURL(referrer_).SchemeIsSecure() && !url().SchemeIsSecure()) { 718#if !defined(OFFICIAL_BUILD) 719 LOG(FATAL) << "Trying to send secure referrer for insecure load"; 720#endif 721 referrer_.clear(); 722 base::RecordAction( 723 base::UserMetricsAction("Net.URLRequest_StartJob_InvalidReferrer")); 724 } 725 726 // Don't allow errors to be sent from within Start(). 727 // TODO(brettw) this may cause NotifyDone to be sent synchronously, 728 // we probably don't want this: they should be sent asynchronously so 729 // the caller does not get reentered. 730 job_->Start(); 731} 732 733void URLRequest::Restart() { 734 // Should only be called if the original job didn't make any progress. 735 DCHECK(job_.get() && !job_->has_response_started()); 736 RestartWithJob( 737 URLRequestJobManager::GetInstance()->CreateJob(this, network_delegate_)); 738} 739 740void URLRequest::RestartWithJob(URLRequestJob *job) { 741 DCHECK(job->request() == this); 742 PrepareToRestart(); 743 StartJob(job); 744} 745 746void URLRequest::Cancel() { 747 DoCancel(ERR_ABORTED, SSLInfo()); 748} 749 750void URLRequest::CancelWithError(int error) { 751 DoCancel(error, SSLInfo()); 752} 753 754void URLRequest::CancelWithSSLError(int error, const SSLInfo& ssl_info) { 755 // This should only be called on a started request. 756 if (!is_pending_ || !job_.get() || job_->has_response_started()) { 757 NOTREACHED(); 758 return; 759 } 760 DoCancel(error, ssl_info); 761} 762 763void URLRequest::DoCancel(int error, const SSLInfo& ssl_info) { 764 DCHECK(error < 0); 765 // If cancelled while calling a delegate, clear delegate info. 766 if (calling_delegate_) { 767 LogUnblocked(); 768 OnCallToDelegateComplete(); 769 } 770 771 // If the URL request already has an error status, then canceling is a no-op. 772 // Plus, we don't want to change the error status once it has been set. 773 if (status_.is_success()) { 774 status_.set_status(URLRequestStatus::CANCELED); 775 status_.set_error(error); 776 response_info_.ssl_info = ssl_info; 777 778 // If the request hasn't already been completed, log a cancellation event. 779 if (!has_notified_completion_) { 780 // Don't log an error code on ERR_ABORTED, since that's redundant. 781 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_CANCELLED, 782 error == ERR_ABORTED ? OK : error); 783 } 784 } 785 786 if (is_pending_ && job_.get()) 787 job_->Kill(); 788 789 // We need to notify about the end of this job here synchronously. The 790 // Job sends an asynchronous notification but by the time this is processed, 791 // our |context_| is NULL. 792 NotifyRequestCompleted(); 793 794 // The Job will call our NotifyDone method asynchronously. This is done so 795 // that the Delegate implementation can call Cancel without having to worry 796 // about being called recursively. 797} 798 799bool URLRequest::Read(IOBuffer* dest, int dest_size, int* bytes_read) { 800 DCHECK(job_.get()); 801 DCHECK(bytes_read); 802 *bytes_read = 0; 803 804 // If this is the first read, end the delegate call that may have started in 805 // OnResponseStarted. 806 OnCallToDelegateComplete(); 807 808 // This handles a cancel that happens while paused. 809 // TODO(ahendrickson): DCHECK() that it is not done after 810 // http://crbug.com/115705 is fixed. 811 if (job_->is_done()) 812 return false; 813 814 if (dest_size == 0) { 815 // Caller is not too bright. I guess we've done what they asked. 816 return true; 817 } 818 819 // Once the request fails or is cancelled, read will just return 0 bytes 820 // to indicate end of stream. 821 if (!status_.is_success()) { 822 return true; 823 } 824 825 bool rv = job_->Read(dest, dest_size, bytes_read); 826 // If rv is false, the status cannot be success. 827 DCHECK(rv || status_.status() != URLRequestStatus::SUCCESS); 828 if (rv && *bytes_read <= 0 && status_.is_success()) 829 NotifyRequestCompleted(); 830 return rv; 831} 832 833void URLRequest::StopCaching() { 834 DCHECK(job_.get()); 835 job_->StopCaching(); 836} 837 838void URLRequest::NotifyReceivedRedirect(const GURL& location, 839 bool* defer_redirect) { 840 is_redirecting_ = true; 841 842 URLRequestJob* job = 843 URLRequestJobManager::GetInstance()->MaybeInterceptRedirect( 844 this, network_delegate_, location); 845 if (job) { 846 RestartWithJob(job); 847 } else if (delegate_) { 848 OnCallToDelegate(); 849 delegate_->OnReceivedRedirect(this, location, defer_redirect); 850 // |this| may be have been destroyed here. 851 } 852} 853 854void URLRequest::NotifyBeforeNetworkStart(bool* defer) { 855 if (delegate_ && !notified_before_network_start_) { 856 OnCallToDelegate(); 857 delegate_->OnBeforeNetworkStart(this, defer); 858 if (!*defer) 859 OnCallToDelegateComplete(); 860 notified_before_network_start_ = true; 861 } 862} 863 864void URLRequest::ResumeNetworkStart() { 865 DCHECK(job_); 866 DCHECK(notified_before_network_start_); 867 868 OnCallToDelegateComplete(); 869 job_->ResumeNetworkStart(); 870} 871 872void URLRequest::NotifyResponseStarted() { 873 int net_error = OK; 874 if (!status_.is_success()) 875 net_error = status_.error(); 876 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_URL_REQUEST_START_JOB, 877 net_error); 878 879 URLRequestJob* job = 880 URLRequestJobManager::GetInstance()->MaybeInterceptResponse( 881 this, network_delegate_); 882 if (job) { 883 RestartWithJob(job); 884 } else { 885 if (delegate_) { 886 // In some cases (e.g. an event was canceled), we might have sent the 887 // completion event and receive a NotifyResponseStarted() later. 888 if (!has_notified_completion_ && status_.is_success()) { 889 if (network_delegate_) 890 network_delegate_->NotifyResponseStarted(this); 891 } 892 893 // Notify in case the entire URL Request has been finished. 894 if (!has_notified_completion_ && !status_.is_success()) 895 NotifyRequestCompleted(); 896 897 OnCallToDelegate(); 898 delegate_->OnResponseStarted(this); 899 // Nothing may appear below this line as OnResponseStarted may delete 900 // |this|. 901 } 902 } 903} 904 905void URLRequest::FollowDeferredRedirect() { 906 CHECK(job_.get()); 907 CHECK(status_.is_success()); 908 909 job_->FollowDeferredRedirect(); 910} 911 912void URLRequest::SetAuth(const AuthCredentials& credentials) { 913 DCHECK(job_.get()); 914 DCHECK(job_->NeedsAuth()); 915 916 job_->SetAuth(credentials); 917} 918 919void URLRequest::CancelAuth() { 920 DCHECK(job_.get()); 921 DCHECK(job_->NeedsAuth()); 922 923 job_->CancelAuth(); 924} 925 926void URLRequest::ContinueWithCertificate(X509Certificate* client_cert) { 927 DCHECK(job_.get()); 928 929 job_->ContinueWithCertificate(client_cert); 930} 931 932void URLRequest::ContinueDespiteLastError() { 933 DCHECK(job_.get()); 934 935 job_->ContinueDespiteLastError(); 936} 937 938void URLRequest::PrepareToRestart() { 939 DCHECK(job_.get()); 940 941 // Close the current URL_REQUEST_START_JOB, since we will be starting a new 942 // one. 943 net_log_.EndEvent(NetLog::TYPE_URL_REQUEST_START_JOB); 944 945 OrphanJob(); 946 947 response_info_ = HttpResponseInfo(); 948 response_info_.request_time = base::Time::Now(); 949 950 load_timing_info_ = LoadTimingInfo(); 951 load_timing_info_.request_start_time = response_info_.request_time; 952 load_timing_info_.request_start = base::TimeTicks::Now(); 953 954 status_ = URLRequestStatus(); 955 is_pending_ = false; 956} 957 958void URLRequest::OrphanJob() { 959 // When calling this function, please check that URLRequestHttpJob is 960 // not in between calling NetworkDelegate::NotifyHeadersReceived receiving 961 // the call back. This is currently guaranteed by the following strategies: 962 // - OrphanJob is called on JobRestart, in this case the URLRequestJob cannot 963 // be receiving any headers at that time. 964 // - OrphanJob is called in ~URLRequest, in this case 965 // NetworkDelegate::NotifyURLRequestDestroyed notifies the NetworkDelegate 966 // that the callback becomes invalid. 967 job_->Kill(); 968 job_->DetachRequest(); // ensures that the job will not call us again 969 job_ = NULL; 970} 971 972int URLRequest::Redirect(const GURL& location, int http_status_code) { 973 // Matches call in NotifyReceivedRedirect. 974 OnCallToDelegateComplete(); 975 if (net_log_.IsLogging()) { 976 net_log_.AddEvent( 977 NetLog::TYPE_URL_REQUEST_REDIRECTED, 978 NetLog::StringCallback("location", &location.possibly_invalid_spec())); 979 } 980 981 if (network_delegate_) 982 network_delegate_->NotifyBeforeRedirect(this, location); 983 984 if (redirect_limit_ <= 0) { 985 DVLOG(1) << "disallowing redirect: exceeds limit"; 986 return ERR_TOO_MANY_REDIRECTS; 987 } 988 989 if (!location.is_valid()) 990 return ERR_INVALID_URL; 991 992 if (!job_->IsSafeRedirect(location)) { 993 DVLOG(1) << "disallowing redirect: unsafe protocol"; 994 return ERR_UNSAFE_REDIRECT; 995 } 996 997 if (!final_upload_progress_.position()) 998 final_upload_progress_ = job_->GetUploadProgress(); 999 PrepareToRestart(); 1000 1001 std::string new_method(ComputeMethodForRedirect(method_, http_status_code)); 1002 if (new_method != method_) { 1003 if (method_ == "POST") { 1004 // If being switched from POST, must remove headers that were specific to 1005 // the POST and don't have meaning in other methods. For example the 1006 // inclusion of a multipart Content-Type header in GET can cause problems 1007 // with some servers: 1008 // http://code.google.com/p/chromium/issues/detail?id=843 1009 StripPostSpecificHeaders(&extra_request_headers_); 1010 } 1011 upload_data_stream_.reset(); 1012 method_.swap(new_method); 1013 } 1014 1015 // Suppress the referrer if we're redirecting out of https. 1016 if (referrer_policy_ == 1017 CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE && 1018 GURL(referrer_).SchemeIsSecure() && !location.SchemeIsSecure()) { 1019 referrer_.clear(); 1020 } 1021 1022 url_chain_.push_back(location); 1023 --redirect_limit_; 1024 1025 Start(); 1026 return OK; 1027} 1028 1029const URLRequestContext* URLRequest::context() const { 1030 return context_; 1031} 1032 1033int64 URLRequest::GetExpectedContentSize() const { 1034 int64 expected_content_size = -1; 1035 if (job_.get()) 1036 expected_content_size = job_->expected_content_size(); 1037 1038 return expected_content_size; 1039} 1040 1041void URLRequest::SetPriority(RequestPriority priority) { 1042 DCHECK_GE(priority, MINIMUM_PRIORITY); 1043 DCHECK_LE(priority, MAXIMUM_PRIORITY); 1044 1045 if ((load_flags_ & LOAD_IGNORE_LIMITS) && (priority != MAXIMUM_PRIORITY)) { 1046 NOTREACHED(); 1047 // Maintain the invariant that requests with IGNORE_LIMITS set 1048 // have MAXIMUM_PRIORITY for release mode. 1049 return; 1050 } 1051 1052 if (priority_ == priority) 1053 return; 1054 1055 priority_ = priority; 1056 if (job_.get()) { 1057 net_log_.AddEvent(NetLog::TYPE_URL_REQUEST_SET_PRIORITY, 1058 NetLog::IntegerCallback("priority", priority_)); 1059 job_->SetPriority(priority_); 1060 } 1061} 1062 1063bool URLRequest::GetHSTSRedirect(GURL* redirect_url) const { 1064 const GURL& url = this->url(); 1065 if (!url.SchemeIs("http")) 1066 return false; 1067 TransportSecurityState* state = context()->transport_security_state(); 1068 if (state && 1069 state->ShouldUpgradeToSSL( 1070 url.host(), 1071 SSLConfigService::IsSNIAvailable(context()->ssl_config_service()))) { 1072 url::Replacements<char> replacements; 1073 const char kNewScheme[] = "https"; 1074 replacements.SetScheme(kNewScheme, url::Component(0, strlen(kNewScheme))); 1075 *redirect_url = url.ReplaceComponents(replacements); 1076 return true; 1077 } 1078 return false; 1079} 1080 1081void URLRequest::NotifyAuthRequired(AuthChallengeInfo* auth_info) { 1082 NetworkDelegate::AuthRequiredResponse rv = 1083 NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION; 1084 auth_info_ = auth_info; 1085 if (network_delegate_) { 1086 OnCallToDelegate(); 1087 rv = network_delegate_->NotifyAuthRequired( 1088 this, 1089 *auth_info, 1090 base::Bind(&URLRequest::NotifyAuthRequiredComplete, 1091 base::Unretained(this)), 1092 &auth_credentials_); 1093 if (rv == NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING) 1094 return; 1095 } 1096 1097 NotifyAuthRequiredComplete(rv); 1098} 1099 1100void URLRequest::NotifyAuthRequiredComplete( 1101 NetworkDelegate::AuthRequiredResponse result) { 1102 OnCallToDelegateComplete(); 1103 1104 // Check that there are no callbacks to already canceled requests. 1105 DCHECK_NE(URLRequestStatus::CANCELED, status_.status()); 1106 1107 // NotifyAuthRequired may be called multiple times, such as 1108 // when an authentication attempt fails. Clear out the data 1109 // so it can be reset on another round. 1110 AuthCredentials credentials = auth_credentials_; 1111 auth_credentials_ = AuthCredentials(); 1112 scoped_refptr<AuthChallengeInfo> auth_info; 1113 auth_info.swap(auth_info_); 1114 1115 switch (result) { 1116 case NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION: 1117 // Defer to the URLRequest::Delegate, since the NetworkDelegate 1118 // didn't take an action. 1119 if (delegate_) 1120 delegate_->OnAuthRequired(this, auth_info.get()); 1121 break; 1122 1123 case NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH: 1124 SetAuth(credentials); 1125 break; 1126 1127 case NetworkDelegate::AUTH_REQUIRED_RESPONSE_CANCEL_AUTH: 1128 CancelAuth(); 1129 break; 1130 1131 case NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING: 1132 NOTREACHED(); 1133 break; 1134 } 1135} 1136 1137void URLRequest::NotifyCertificateRequested( 1138 SSLCertRequestInfo* cert_request_info) { 1139 if (delegate_) 1140 delegate_->OnCertificateRequested(this, cert_request_info); 1141} 1142 1143void URLRequest::NotifySSLCertificateError(const SSLInfo& ssl_info, 1144 bool fatal) { 1145 if (delegate_) 1146 delegate_->OnSSLCertificateError(this, ssl_info, fatal); 1147} 1148 1149bool URLRequest::CanGetCookies(const CookieList& cookie_list) const { 1150 DCHECK(!(load_flags_ & LOAD_DO_NOT_SEND_COOKIES)); 1151 if (network_delegate_) { 1152 return network_delegate_->CanGetCookies(*this, cookie_list); 1153 } 1154 return g_default_can_use_cookies; 1155} 1156 1157bool URLRequest::CanSetCookie(const std::string& cookie_line, 1158 CookieOptions* options) const { 1159 DCHECK(!(load_flags_ & LOAD_DO_NOT_SAVE_COOKIES)); 1160 if (network_delegate_) { 1161 return network_delegate_->CanSetCookie(*this, cookie_line, options); 1162 } 1163 return g_default_can_use_cookies; 1164} 1165 1166bool URLRequest::CanEnablePrivacyMode() const { 1167 if (network_delegate_) { 1168 return network_delegate_->CanEnablePrivacyMode(url(), 1169 first_party_for_cookies_); 1170 } 1171 return !g_default_can_use_cookies; 1172} 1173 1174 1175void URLRequest::NotifyReadCompleted(int bytes_read) { 1176 // Notify in case the entire URL Request has been finished. 1177 if (bytes_read <= 0) 1178 NotifyRequestCompleted(); 1179 1180 // Notify NetworkChangeNotifier that we just received network data. 1181 // This is to identify cases where the NetworkChangeNotifier thinks we 1182 // are off-line but we are still receiving network data (crbug.com/124069), 1183 // and to get rough network connection measurements. 1184 if (bytes_read > 0 && !was_cached()) 1185 NetworkChangeNotifier::NotifyDataReceived(*this, bytes_read); 1186 1187 if (delegate_) 1188 delegate_->OnReadCompleted(this, bytes_read); 1189 1190 // Nothing below this line as OnReadCompleted may delete |this|. 1191} 1192 1193void URLRequest::OnHeadersComplete() { 1194 // Cache load timing information now, as information will be lost once the 1195 // socket is closed and the ClientSocketHandle is Reset, which will happen 1196 // once the body is complete. The start times should already be populated. 1197 if (job_.get()) { 1198 // Keep a copy of the two times the URLRequest sets. 1199 base::TimeTicks request_start = load_timing_info_.request_start; 1200 base::Time request_start_time = load_timing_info_.request_start_time; 1201 1202 // Clear load times. Shouldn't be neded, but gives the GetLoadTimingInfo a 1203 // consistent place to start from. 1204 load_timing_info_ = LoadTimingInfo(); 1205 job_->GetLoadTimingInfo(&load_timing_info_); 1206 1207 load_timing_info_.request_start = request_start; 1208 load_timing_info_.request_start_time = request_start_time; 1209 1210 ConvertRealLoadTimesToBlockingTimes(&load_timing_info_); 1211 } 1212} 1213 1214void URLRequest::NotifyRequestCompleted() { 1215 // TODO(battre): Get rid of this check, according to willchan it should 1216 // not be needed. 1217 if (has_notified_completion_) 1218 return; 1219 1220 is_pending_ = false; 1221 is_redirecting_ = false; 1222 has_notified_completion_ = true; 1223 if (network_delegate_) 1224 network_delegate_->NotifyCompleted(this, job_.get() != NULL); 1225} 1226 1227void URLRequest::OnCallToDelegate() { 1228 DCHECK(!calling_delegate_); 1229 DCHECK(blocked_by_.empty()); 1230 calling_delegate_ = true; 1231 net_log_.BeginEvent(NetLog::TYPE_URL_REQUEST_DELEGATE); 1232} 1233 1234void URLRequest::OnCallToDelegateComplete() { 1235 // This should have been cleared before resuming the request. 1236 DCHECK(blocked_by_.empty()); 1237 if (!calling_delegate_) 1238 return; 1239 calling_delegate_ = false; 1240 net_log_.EndEvent(NetLog::TYPE_URL_REQUEST_DELEGATE); 1241} 1242 1243void URLRequest::set_stack_trace(const base::debug::StackTrace& stack_trace) { 1244 base::debug::StackTrace* stack_trace_copy = 1245 new base::debug::StackTrace(NULL, 0); 1246 *stack_trace_copy = stack_trace; 1247 stack_trace_.reset(stack_trace_copy); 1248} 1249 1250const base::debug::StackTrace* URLRequest::stack_trace() const { 1251 return stack_trace_.get(); 1252} 1253 1254} // namespace net 1255