url_request.cc revision 868fa2fe829687343ffae624259930155e16dbd8
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/url_request/url_request.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/callback.h"
10#include "base/compiler_specific.h"
11#include "base/debug/stack_trace.h"
12#include "base/lazy_instance.h"
13#include "base/memory/singleton.h"
14#include "base/message_loop.h"
15#include "base/metrics/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
38using base::Time;
39using std::string;
40
41namespace net {
42
43namespace {
44
45// Max number of http redirects to follow.  Same number as gecko.
46const int kMaxRedirects = 20;
47
48// Discard headers which have meaning in POST (Content-Length, Content-Type,
49// Origin).
50void 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.
60uint64 g_next_url_request_identifier = 1;
61
62// This lock protects g_next_url_request_identifier.
63base::LazyInstance<base::Lock>::Leaky
64    g_next_url_request_identifier_lock = LAZY_INSTANCE_INITIALIZER;
65
66// Returns an prior unused identifier for URL requests.
67uint64 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.
73bool g_url_requests_started = false;
74
75// True if cookies are accepted by default.
76bool 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.
91void 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
142URLRequest::ProtocolFactory*
143URLRequest::Deprecated::RegisterProtocolFactory(const std::string& scheme,
144                                                ProtocolFactory* factory) {
145  return URLRequest::RegisterProtocolFactory(scheme, factory);
146}
147
148void URLRequest::Deprecated::RegisterRequestInterceptor(
149    Interceptor* interceptor) {
150  URLRequest::RegisterRequestInterceptor(interceptor);
151}
152
153void URLRequest::Deprecated::UnregisterRequestInterceptor(
154    Interceptor* interceptor) {
155  URLRequest::UnregisterRequestInterceptor(interceptor);
156}
157
158///////////////////////////////////////////////////////////////////////////////
159// URLRequest::Interceptor
160
161URLRequestJob* URLRequest::Interceptor::MaybeInterceptRedirect(
162    URLRequest* request,
163    NetworkDelegate* network_delegate,
164    const GURL& location) {
165  return NULL;
166}
167
168URLRequestJob* URLRequest::Interceptor::MaybeInterceptResponse(
169    URLRequest* request, NetworkDelegate* network_delegate) {
170  return NULL;
171}
172
173///////////////////////////////////////////////////////////////////////////////
174// URLRequest::Delegate
175
176void URLRequest::Delegate::OnReceivedRedirect(URLRequest* request,
177                                              const GURL& new_url,
178                                              bool* defer_redirect) {
179}
180
181void URLRequest::Delegate::OnAuthRequired(URLRequest* request,
182                                          AuthChallengeInfo* auth_info) {
183  request->CancelAuth();
184}
185
186void URLRequest::Delegate::OnCertificateRequested(
187    URLRequest* request,
188    SSLCertRequestInfo* cert_request_info) {
189  request->Cancel();
190}
191
192void 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.
202URLRequest::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
237URLRequest::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
273URLRequest::~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
297URLRequest::ProtocolFactory* URLRequest::RegisterProtocolFactory(
298    const string& scheme, ProtocolFactory* factory) {
299  return URLRequestJobManager::GetInstance()->RegisterProtocolFactory(scheme,
300                                                                      factory);
301}
302
303// static
304void URLRequest::RegisterRequestInterceptor(Interceptor* interceptor) {
305  URLRequestJobManager::GetInstance()->RegisterRequestInterceptor(interceptor);
306}
307
308// static
309void URLRequest::UnregisterRequestInterceptor(Interceptor* interceptor) {
310  URLRequestJobManager::GetInstance()->UnregisterRequestInterceptor(
311      interceptor);
312}
313
314void 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
322void 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
331void URLRequest::set_upload(scoped_ptr<UploadDataStream> upload) {
332  DCHECK(!upload->is_chunked());
333  upload_data_stream_ = upload.Pass();
334}
335
336const UploadDataStream* URLRequest::get_upload() const {
337  return upload_data_stream_.get();
338}
339
340bool URLRequest::has_upload() const {
341  return upload_data_stream_.get() != NULL;
342}
343
344void URLRequest::SetExtraRequestHeaderById(int id, const string& value,
345                                           bool overwrite) {
346  DCHECK(!is_pending_ || is_redirecting_);
347  NOTREACHED() << "implement me!";
348}
349
350void 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
361void URLRequest::RemoveRequestHeaderByName(const string& name) {
362  DCHECK(!is_pending_ || is_redirecting_);
363  extra_request_headers_.RemoveHeader(name);
364}
365
366void 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
375LoadStateWithParam URLRequest::GetLoadState() const {
376  if (blocked_on_delegate_) {
377    return LoadStateWithParam(LOAD_STATE_WAITING_FOR_DELEGATE,
378                              load_state_param_);
379  }
380  return LoadStateWithParam(job_.get() ? job_->GetLoadState() : LOAD_STATE_IDLE,
381                            base::string16());
382}
383
384UploadProgress URLRequest::GetUploadProgress() const {
385  if (!job_.get()) {
386    // We haven't started or the request was cancelled
387    return UploadProgress();
388  }
389  if (final_upload_progress_.position()) {
390    // The first job completed and none of the subsequent series of
391    // GETs when following redirects will upload anything, so we return the
392    // cached results from the initial job, the POST.
393    return final_upload_progress_;
394  }
395  return job_->GetUploadProgress();
396}
397
398void URLRequest::GetResponseHeaderById(int id, string* value) {
399  DCHECK(job_.get());
400  NOTREACHED() << "implement me!";
401}
402
403void URLRequest::GetResponseHeaderByName(const string& name, string* value) {
404  DCHECK(value);
405  if (response_info_.headers.get()) {
406    response_info_.headers->GetNormalizedHeader(name, value);
407  } else {
408    value->clear();
409  }
410}
411
412void URLRequest::GetAllResponseHeaders(string* headers) {
413  DCHECK(headers);
414  if (response_info_.headers.get()) {
415    response_info_.headers->GetNormalizedHeaders(headers);
416  } else {
417    headers->clear();
418  }
419}
420
421HostPortPair URLRequest::GetSocketAddress() const {
422  DCHECK(job_.get());
423  return job_->GetSocketAddress();
424}
425
426HttpResponseHeaders* URLRequest::response_headers() const {
427  return response_info_.headers.get();
428}
429
430void URLRequest::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
431  *load_timing_info = load_timing_info_;
432}
433
434bool URLRequest::GetResponseCookies(ResponseCookies* cookies) {
435  DCHECK(job_.get());
436  return job_->GetResponseCookies(cookies);
437}
438
439void URLRequest::GetMimeType(string* mime_type) {
440  DCHECK(job_.get());
441  job_->GetMimeType(mime_type);
442}
443
444void URLRequest::GetCharset(string* charset) {
445  DCHECK(job_.get());
446  job_->GetCharset(charset);
447}
448
449int URLRequest::GetResponseCode() {
450  DCHECK(job_.get());
451  return job_->GetResponseCode();
452}
453
454// static
455void URLRequest::SetDefaultCookiePolicyToBlock() {
456  CHECK(!g_url_requests_started);
457  g_default_can_use_cookies = false;
458}
459
460// static
461bool URLRequest::IsHandledProtocol(const std::string& scheme) {
462  return URLRequestJobManager::GetInstance()->SupportsScheme(scheme);
463}
464
465// static
466bool URLRequest::IsHandledURL(const GURL& url) {
467  if (!url.is_valid()) {
468    // We handle error cases.
469    return true;
470  }
471
472  return IsHandledProtocol(url.scheme());
473}
474
475void URLRequest::set_first_party_for_cookies(
476    const GURL& first_party_for_cookies) {
477  first_party_for_cookies_ = first_party_for_cookies;
478}
479
480void URLRequest::set_method(const std::string& method) {
481  DCHECK(!is_pending_);
482  method_ = method;
483}
484
485void URLRequest::SetReferrer(const std::string& referrer) {
486  DCHECK(!is_pending_);
487  referrer_ = referrer;
488  // Ensure that we do not send URL fragment, username and password
489  // fields in the referrer.
490  GURL referrer_url(referrer);
491  UMA_HISTOGRAM_BOOLEAN("Net.URLRequest_SetReferrer_IsEmptyOrValid",
492                        referrer_url.is_empty() || referrer_url.is_valid());
493  if (referrer_url.is_valid() && (referrer_url.has_ref() ||
494      referrer_url.has_username() ||  referrer_url.has_password())) {
495    GURL::Replacements referrer_mods;
496    referrer_mods.ClearRef();
497    referrer_mods.ClearUsername();
498    referrer_mods.ClearPassword();
499    referrer_url = referrer_url.ReplaceComponents(referrer_mods);
500    referrer_ = referrer_url.spec();
501  }
502}
503
504void URLRequest::set_referrer_policy(ReferrerPolicy referrer_policy) {
505  DCHECK(!is_pending_);
506  referrer_policy_ = referrer_policy;
507}
508
509void URLRequest::set_delegate(Delegate* delegate) {
510  delegate_ = delegate;
511}
512
513void URLRequest::Start() {
514  DCHECK_EQ(network_delegate_, context_->network_delegate());
515
516  g_url_requests_started = true;
517  response_info_.request_time = base::Time::Now();
518
519  load_timing_info_ = LoadTimingInfo();
520  load_timing_info_.request_start_time = response_info_.request_time;
521  load_timing_info_.request_start = base::TimeTicks::Now();
522
523  // Only notify the delegate for the initial request.
524  if (network_delegate_) {
525    int error = network_delegate_->NotifyBeforeURLRequest(
526        this, before_request_callback_, &delegate_redirect_url_);
527    if (error == net::ERR_IO_PENDING) {
528      // Paused on the delegate, will invoke |before_request_callback_| later.
529      SetBlockedOnDelegate();
530    } else {
531      BeforeRequestComplete(error);
532    }
533    return;
534  }
535
536  StartJob(URLRequestJobManager::GetInstance()->CreateJob(
537      this, network_delegate_));
538}
539
540///////////////////////////////////////////////////////////////////////////////
541
542void URLRequest::BeforeRequestComplete(int error) {
543  DCHECK(!job_.get());
544  DCHECK_NE(ERR_IO_PENDING, error);
545  DCHECK_EQ(network_delegate_, context_->network_delegate());
546
547  // Check that there are no callbacks to already canceled requests.
548  DCHECK_NE(URLRequestStatus::CANCELED, status_.status());
549
550  if (blocked_on_delegate_)
551    SetUnblockedOnDelegate();
552
553  if (error != OK) {
554    std::string source("delegate");
555    net_log_.AddEvent(NetLog::TYPE_CANCELLED,
556                      NetLog::StringCallback("source", &source));
557    StartJob(new URLRequestErrorJob(this, network_delegate_, error));
558  } else if (!delegate_redirect_url_.is_empty()) {
559    GURL new_url;
560    new_url.Swap(&delegate_redirect_url_);
561
562    URLRequestRedirectJob* job = new URLRequestRedirectJob(
563        this, network_delegate_, new_url,
564        // Use status code 307 to preserve the method, so POST requests work.
565        URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT);
566    StartJob(job);
567  } else {
568    StartJob(URLRequestJobManager::GetInstance()->CreateJob(
569        this, network_delegate_));
570  }
571}
572
573void URLRequest::StartJob(URLRequestJob* job) {
574  DCHECK(!is_pending_);
575  DCHECK(!job_.get());
576
577  net_log_.BeginEvent(
578      NetLog::TYPE_URL_REQUEST_START_JOB,
579      base::Bind(&NetLogURLRequestStartCallback,
580                 &url(), &method_, load_flags_, priority_,
581                 upload_data_stream_ ? upload_data_stream_->identifier() : -1));
582
583  job_ = job;
584  job_->SetExtraRequestHeaders(extra_request_headers_);
585  job_->SetPriority(priority_);
586
587  if (upload_data_stream_.get())
588    job_->SetUpload(upload_data_stream_.get());
589
590  is_pending_ = true;
591  is_redirecting_ = false;
592
593  response_info_.was_cached = false;
594
595  // Don't allow errors to be sent from within Start().
596  // TODO(brettw) this may cause NotifyDone to be sent synchronously,
597  // we probably don't want this: they should be sent asynchronously so
598  // the caller does not get reentered.
599  job_->Start();
600}
601
602void URLRequest::Restart() {
603  // Should only be called if the original job didn't make any progress.
604  DCHECK(job_.get() && !job_->has_response_started());
605  RestartWithJob(
606      URLRequestJobManager::GetInstance()->CreateJob(this, network_delegate_));
607}
608
609void URLRequest::RestartWithJob(URLRequestJob *job) {
610  DCHECK(job->request() == this);
611  PrepareToRestart();
612  StartJob(job);
613}
614
615void URLRequest::Cancel() {
616  DoCancel(ERR_ABORTED, SSLInfo());
617}
618
619void URLRequest::CancelWithError(int error) {
620  DoCancel(error, SSLInfo());
621}
622
623void URLRequest::CancelWithSSLError(int error, const SSLInfo& ssl_info) {
624  // This should only be called on a started request.
625  if (!is_pending_ || !job_.get() || job_->has_response_started()) {
626    NOTREACHED();
627    return;
628  }
629  DoCancel(error, ssl_info);
630}
631
632void URLRequest::DoCancel(int error, const SSLInfo& ssl_info) {
633  DCHECK(error < 0);
634
635  // If the URL request already has an error status, then canceling is a no-op.
636  // Plus, we don't want to change the error status once it has been set.
637  if (status_.is_success()) {
638    status_.set_status(URLRequestStatus::CANCELED);
639    status_.set_error(error);
640    response_info_.ssl_info = ssl_info;
641
642    // If the request hasn't already been completed, log a cancellation event.
643    if (!has_notified_completion_) {
644      // Don't log an error code on ERR_ABORTED, since that's redundant.
645      net_log_.AddEventWithNetErrorCode(NetLog::TYPE_CANCELLED,
646                                        error == ERR_ABORTED ? OK : error);
647    }
648  }
649
650  if (is_pending_ && job_.get())
651    job_->Kill();
652
653  // We need to notify about the end of this job here synchronously. The
654  // Job sends an asynchronous notification but by the time this is processed,
655  // our |context_| is NULL.
656  NotifyRequestCompleted();
657
658  // The Job will call our NotifyDone method asynchronously.  This is done so
659  // that the Delegate implementation can call Cancel without having to worry
660  // about being called recursively.
661}
662
663bool URLRequest::Read(IOBuffer* dest, int dest_size, int* bytes_read) {
664  DCHECK(job_.get());
665  DCHECK(bytes_read);
666  *bytes_read = 0;
667
668  // This handles a cancel that happens while paused.
669  // TODO(ahendrickson): DCHECK() that it is not done after
670  // http://crbug.com/115705 is fixed.
671  if (job_->is_done())
672    return false;
673
674  if (dest_size == 0) {
675    // Caller is not too bright.  I guess we've done what they asked.
676    return true;
677  }
678
679  // Once the request fails or is cancelled, read will just return 0 bytes
680  // to indicate end of stream.
681  if (!status_.is_success()) {
682    return true;
683  }
684
685  bool rv = job_->Read(dest, dest_size, bytes_read);
686  // If rv is false, the status cannot be success.
687  DCHECK(rv || status_.status() != URLRequestStatus::SUCCESS);
688  if (rv && *bytes_read <= 0 && status_.is_success())
689    NotifyRequestCompleted();
690  return rv;
691}
692
693void URLRequest::StopCaching() {
694  DCHECK(job_.get());
695  job_->StopCaching();
696}
697
698void URLRequest::NotifyReceivedRedirect(const GURL& location,
699                                        bool* defer_redirect) {
700  is_redirecting_ = true;
701
702  URLRequestJob* job =
703      URLRequestJobManager::GetInstance()->MaybeInterceptRedirect(
704          this, network_delegate_, location);
705  if (job) {
706    RestartWithJob(job);
707  } else if (delegate_) {
708    delegate_->OnReceivedRedirect(this, location, defer_redirect);
709    // |this| may be have been destroyed here.
710  }
711}
712
713void URLRequest::NotifyResponseStarted() {
714  int net_error = OK;
715  if (!status_.is_success())
716    net_error = status_.error();
717  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_URL_REQUEST_START_JOB,
718                                    net_error);
719
720  URLRequestJob* job =
721      URLRequestJobManager::GetInstance()->MaybeInterceptResponse(
722          this, network_delegate_);
723  if (job) {
724    RestartWithJob(job);
725  } else {
726    if (delegate_) {
727      // In some cases (e.g. an event was canceled), we might have sent the
728      // completion event and receive a NotifyResponseStarted() later.
729      if (!has_notified_completion_ && status_.is_success()) {
730        if (network_delegate_)
731          network_delegate_->NotifyResponseStarted(this);
732      }
733
734      // Notify in case the entire URL Request has been finished.
735      if (!has_notified_completion_ && !status_.is_success())
736        NotifyRequestCompleted();
737
738      delegate_->OnResponseStarted(this);
739      // Nothing may appear below this line as OnResponseStarted may delete
740      // |this|.
741    }
742  }
743}
744
745void URLRequest::FollowDeferredRedirect() {
746  CHECK(job_.get());
747  CHECK(status_.is_success());
748
749  job_->FollowDeferredRedirect();
750}
751
752void URLRequest::SetAuth(const AuthCredentials& credentials) {
753  DCHECK(job_.get());
754  DCHECK(job_->NeedsAuth());
755
756  job_->SetAuth(credentials);
757}
758
759void URLRequest::CancelAuth() {
760  DCHECK(job_.get());
761  DCHECK(job_->NeedsAuth());
762
763  job_->CancelAuth();
764}
765
766void URLRequest::ContinueWithCertificate(X509Certificate* client_cert) {
767  DCHECK(job_.get());
768
769  job_->ContinueWithCertificate(client_cert);
770}
771
772void URLRequest::ContinueDespiteLastError() {
773  DCHECK(job_.get());
774
775  job_->ContinueDespiteLastError();
776}
777
778void URLRequest::PrepareToRestart() {
779  DCHECK(job_.get());
780
781  // Close the current URL_REQUEST_START_JOB, since we will be starting a new
782  // one.
783  net_log_.EndEvent(NetLog::TYPE_URL_REQUEST_START_JOB);
784
785  OrphanJob();
786
787  response_info_ = HttpResponseInfo();
788  response_info_.request_time = base::Time::Now();
789
790  load_timing_info_ = LoadTimingInfo();
791  load_timing_info_.request_start_time = response_info_.request_time;
792  load_timing_info_.request_start = base::TimeTicks::Now();
793
794  status_ = URLRequestStatus();
795  is_pending_ = false;
796}
797
798void URLRequest::OrphanJob() {
799  // When calling this function, please check that URLRequestHttpJob is
800  // not in between calling NetworkDelegate::NotifyHeadersReceived receiving
801  // the call back. This is currently guaranteed by the following strategies:
802  // - OrphanJob is called on JobRestart, in this case the URLRequestJob cannot
803  //   be receiving any headers at that time.
804  // - OrphanJob is called in ~URLRequest, in this case
805  //   NetworkDelegate::NotifyURLRequestDestroyed notifies the NetworkDelegate
806  //   that the callback becomes invalid.
807  job_->Kill();
808  job_->DetachRequest();  // ensures that the job will not call us again
809  job_ = NULL;
810}
811
812int URLRequest::Redirect(const GURL& location, int http_status_code) {
813  if (net_log_.IsLoggingAllEvents()) {
814    net_log_.AddEvent(
815        NetLog::TYPE_URL_REQUEST_REDIRECTED,
816        NetLog::StringCallback("location", &location.possibly_invalid_spec()));
817  }
818
819  if (network_delegate_)
820    network_delegate_->NotifyBeforeRedirect(this, location);
821
822  if (redirect_limit_ <= 0) {
823    DVLOG(1) << "disallowing redirect: exceeds limit";
824    return ERR_TOO_MANY_REDIRECTS;
825  }
826
827  if (!location.is_valid())
828    return ERR_INVALID_URL;
829
830  if (!job_->IsSafeRedirect(location)) {
831    DVLOG(1) << "disallowing redirect: unsafe protocol";
832    return ERR_UNSAFE_REDIRECT;
833  }
834
835  if (!final_upload_progress_.position())
836    final_upload_progress_ = job_->GetUploadProgress();
837  PrepareToRestart();
838
839  // For 303 redirects, all request methods except HEAD are converted to GET,
840  // as per the latest httpbis draft.  The draft also allows POST requests to
841  // be converted to GETs when following 301/302 redirects, for historical
842  // reasons. Most major browsers do this and so shall we.  Both RFC 2616 and
843  // the httpbis draft say to prompt the user to confirm the generation of new
844  // requests, other than GET and HEAD requests, but IE omits these prompts and
845  // so shall we.
846  // See:  https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-17#section-7.3
847  bool was_post = method_ == "POST";
848  if ((http_status_code == 303 && method_ != "HEAD") ||
849      ((http_status_code == 301 || http_status_code == 302) && was_post)) {
850    method_ = "GET";
851    upload_data_stream_.reset();
852    if (was_post) {
853      // If being switched from POST to GET, must remove headers that were
854      // specific to the POST and don't have meaning in GET. For example
855      // the inclusion of a multipart Content-Type header in GET can cause
856      // problems with some servers:
857      // http://code.google.com/p/chromium/issues/detail?id=843
858      StripPostSpecificHeaders(&extra_request_headers_);
859    }
860  }
861
862  // Suppress the referrer if we're redirecting out of https.
863  if (referrer_policy_ ==
864          CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE &&
865      GURL(referrer_).SchemeIsSecure() && !location.SchemeIsSecure()) {
866    referrer_.clear();
867  }
868
869  url_chain_.push_back(location);
870  --redirect_limit_;
871
872  Start();
873  return OK;
874}
875
876const URLRequestContext* URLRequest::context() const {
877  return context_;
878}
879
880int64 URLRequest::GetExpectedContentSize() const {
881  int64 expected_content_size = -1;
882  if (job_.get())
883    expected_content_size = job_->expected_content_size();
884
885  return expected_content_size;
886}
887
888void URLRequest::SetPriority(RequestPriority priority) {
889  DCHECK_GE(priority, MINIMUM_PRIORITY);
890  DCHECK_LT(priority, NUM_PRIORITIES);
891  if (priority_ == priority)
892    return;
893
894  priority_ = priority;
895  if (job_.get()) {
896    net_log_.AddEvent(NetLog::TYPE_URL_REQUEST_SET_PRIORITY,
897                      NetLog::IntegerCallback("priority", priority_));
898    job_->SetPriority(priority_);
899  }
900}
901
902bool URLRequest::GetHSTSRedirect(GURL* redirect_url) const {
903  const GURL& url = this->url();
904  if (!url.SchemeIs("http"))
905    return false;
906  TransportSecurityState::DomainState domain_state;
907  if (context()->transport_security_state() &&
908      context()->transport_security_state()->GetDomainState(
909          url.host(),
910          SSLConfigService::IsSNIAvailable(context()->ssl_config_service()),
911          &domain_state) &&
912      domain_state.ShouldUpgradeToSSL()) {
913    url_canon::Replacements<char> replacements;
914    const char kNewScheme[] = "https";
915    replacements.SetScheme(kNewScheme,
916                           url_parse::Component(0, strlen(kNewScheme)));
917    *redirect_url = url.ReplaceComponents(replacements);
918    return true;
919  }
920  return false;
921}
922
923void URLRequest::NotifyAuthRequired(AuthChallengeInfo* auth_info) {
924  NetworkDelegate::AuthRequiredResponse rv =
925      NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
926  auth_info_ = auth_info;
927  if (network_delegate_) {
928    rv = network_delegate_->NotifyAuthRequired(
929        this,
930        *auth_info,
931        base::Bind(&URLRequest::NotifyAuthRequiredComplete,
932                   base::Unretained(this)),
933        &auth_credentials_);
934  }
935
936  if (rv == NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING) {
937    SetBlockedOnDelegate();
938  } else {
939    NotifyAuthRequiredComplete(rv);
940  }
941}
942
943void URLRequest::NotifyAuthRequiredComplete(
944    NetworkDelegate::AuthRequiredResponse result) {
945  SetUnblockedOnDelegate();
946
947  // Check that there are no callbacks to already canceled requests.
948  DCHECK_NE(URLRequestStatus::CANCELED, status_.status());
949
950  // NotifyAuthRequired may be called multiple times, such as
951  // when an authentication attempt fails. Clear out the data
952  // so it can be reset on another round.
953  AuthCredentials credentials = auth_credentials_;
954  auth_credentials_ = AuthCredentials();
955  scoped_refptr<AuthChallengeInfo> auth_info;
956  auth_info.swap(auth_info_);
957
958  switch (result) {
959    case NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION:
960      // Defer to the URLRequest::Delegate, since the NetworkDelegate
961      // didn't take an action.
962      if (delegate_)
963        delegate_->OnAuthRequired(this, auth_info.get());
964      break;
965
966    case NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH:
967      SetAuth(credentials);
968      break;
969
970    case NetworkDelegate::AUTH_REQUIRED_RESPONSE_CANCEL_AUTH:
971      CancelAuth();
972      break;
973
974    case NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING:
975      NOTREACHED();
976      break;
977  }
978}
979
980void URLRequest::NotifyCertificateRequested(
981    SSLCertRequestInfo* cert_request_info) {
982  if (delegate_)
983    delegate_->OnCertificateRequested(this, cert_request_info);
984}
985
986void URLRequest::NotifySSLCertificateError(const SSLInfo& ssl_info,
987                                           bool fatal) {
988  if (delegate_)
989    delegate_->OnSSLCertificateError(this, ssl_info, fatal);
990}
991
992bool URLRequest::CanGetCookies(const CookieList& cookie_list) const {
993  DCHECK(!(load_flags_ & LOAD_DO_NOT_SEND_COOKIES));
994  if (network_delegate_) {
995    return network_delegate_->CanGetCookies(*this, cookie_list);
996  }
997  return g_default_can_use_cookies;
998}
999
1000bool URLRequest::CanSetCookie(const std::string& cookie_line,
1001                              CookieOptions* options) const {
1002  DCHECK(!(load_flags_ & LOAD_DO_NOT_SAVE_COOKIES));
1003  if (network_delegate_) {
1004    return network_delegate_->CanSetCookie(*this, cookie_line, options);
1005  }
1006  return g_default_can_use_cookies;
1007}
1008
1009bool URLRequest::CanEnablePrivacyMode() const {
1010  if (network_delegate_) {
1011    return network_delegate_->CanEnablePrivacyMode(url(),
1012                                                   first_party_for_cookies_);
1013  }
1014  return !g_default_can_use_cookies;
1015}
1016
1017
1018void URLRequest::NotifyReadCompleted(int bytes_read) {
1019  // Notify in case the entire URL Request has been finished.
1020  if (bytes_read <= 0)
1021    NotifyRequestCompleted();
1022
1023  // Notify NetworkChangeNotifier that we just received network data.
1024  // This is to identify cases where the NetworkChangeNotifier thinks we
1025  // are off-line but we are still receiving network data (crbug.com/124069),
1026  // and to get rough network connection measurements.
1027  if (bytes_read > 0 && !was_cached())
1028    NetworkChangeNotifier::NotifyDataReceived(*this, bytes_read);
1029
1030  if (delegate_)
1031    delegate_->OnReadCompleted(this, bytes_read);
1032
1033  // Nothing below this line as OnReadCompleted may delete |this|.
1034}
1035
1036void URLRequest::OnHeadersComplete() {
1037  // Cache load timing information now, as information will be lost once the
1038  // socket is closed and the ClientSocketHandle is Reset, which will happen
1039  // once the body is complete.  The start times should already be populated.
1040  if (job_.get()) {
1041    // Keep a copy of the two times the URLRequest sets.
1042    base::TimeTicks request_start = load_timing_info_.request_start;
1043    base::Time request_start_time = load_timing_info_.request_start_time;
1044
1045    // Clear load times.  Shouldn't be neded, but gives the GetLoadTimingInfo a
1046    // consistent place to start from.
1047    load_timing_info_ = LoadTimingInfo();
1048    job_->GetLoadTimingInfo(&load_timing_info_);
1049
1050    load_timing_info_.request_start = request_start;
1051    load_timing_info_.request_start_time = request_start_time;
1052
1053    ConvertRealLoadTimesToBlockingTimes(&load_timing_info_);
1054  }
1055}
1056
1057void URLRequest::NotifyRequestCompleted() {
1058  // TODO(battre): Get rid of this check, according to willchan it should
1059  // not be needed.
1060  if (has_notified_completion_)
1061    return;
1062
1063  is_pending_ = false;
1064  is_redirecting_ = false;
1065  has_notified_completion_ = true;
1066  if (network_delegate_)
1067    network_delegate_->NotifyCompleted(this, job_.get() != NULL);
1068}
1069
1070void URLRequest::SetBlockedOnDelegate() {
1071  blocked_on_delegate_ = true;
1072  if (!load_state_param_.empty()) {
1073    net_log_.BeginEvent(NetLog::TYPE_URL_REQUEST_BLOCKED_ON_DELEGATE,
1074                        NetLog::StringCallback("delegate", &load_state_param_));
1075  } else {
1076    net_log_.BeginEvent(NetLog::TYPE_URL_REQUEST_BLOCKED_ON_DELEGATE);
1077  }
1078}
1079
1080void URLRequest::SetUnblockedOnDelegate() {
1081  if (!blocked_on_delegate_)
1082    return;
1083  blocked_on_delegate_ = false;
1084  load_state_param_.clear();
1085  net_log_.EndEvent(NetLog::TYPE_URL_REQUEST_BLOCKED_ON_DELEGATE);
1086}
1087
1088void URLRequest::set_stack_trace(const base::debug::StackTrace& stack_trace) {
1089  base::debug::StackTrace* stack_trace_copy =
1090      new base::debug::StackTrace(NULL, 0);
1091  *stack_trace_copy = stack_trace;
1092  stack_trace_.reset(stack_trace_copy);
1093}
1094
1095const base::debug::StackTrace* URLRequest::stack_trace() const {
1096  return stack_trace_.get();
1097}
1098
1099}  // namespace net
1100