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