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