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