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