1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be
3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file.
4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/http/http_stream_factory_impl_job.h"
6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/logging.h"
8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/stl_util-inl.h"
9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/string_util.h"
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/stringprintf.h"
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/values.h"
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/connection_type_histograms.h"
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/net_log.h"
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/net_util.h"
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/ssl_cert_request_info.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/http/http_basic_stream.h"
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/http/http_network_session.h"
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/http/http_proxy_client_socket.h"
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/http/http_proxy_client_socket_pool.h"
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/http/http_request_info.h"
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/http/http_stream_factory_impl_request.h"
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/socket/client_socket_handle.h"
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/socket/client_socket_pool.h"
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/socket/socks_client_socket_pool.h"
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/socket/ssl_client_socket.h"
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/socket/ssl_client_socket_pool.h"
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/spdy/spdy_http_stream.h"
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/spdy/spdy_session.h"
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/spdy/spdy_session_pool.h"
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace net {
32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace {
34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}  // namespace
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
37dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenHttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory,
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                HttpNetworkSession* session,
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                const HttpRequestInfo& request_info,
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                const SSLConfig& ssl_config,
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                const BoundNetLog& net_log)
42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    : request_(NULL),
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      request_info_(request_info),
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ssl_config_(ssl_config),
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      net_log_(BoundNetLog::Make(net_log.net_log(),
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                 NetLog::SOURCE_HTTP_STREAM_JOB)),
47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(this, &Job::OnIOComplete)),
48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      connection_(new ClientSocketHandle),
49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      session_(session),
50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      stream_factory_(stream_factory),
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      next_state_(STATE_NONE),
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      pac_request_(NULL),
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      blocking_job_(NULL),
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      dependent_job_(NULL),
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      using_ssl_(false),
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      using_spdy_(false),
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      force_spdy_always_(HttpStreamFactory::force_spdy_always()),
58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()),
59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      spdy_certificate_error_(OK),
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      establishing_tunnel_(false),
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      was_npn_negotiated_(false),
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      num_streams_(0),
63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      spdy_session_direct_(false),
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(stream_factory);
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(session);
67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
69dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenHttpStreamFactoryImpl::Job::~Job() {
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_JOB, NULL);
71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // When we're in a partially constructed state, waiting for the user to
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // provide certificate handling information or authentication, we can't reuse
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // this stream at all.
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (next_state_ == STATE_WAITING_USER_ACTION) {
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    connection_->socket()->Disconnect();
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    connection_.reset();
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (pac_request_)
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    session_->proxy_service()->CancelPacRequest(pac_request_);
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // The stream could be in a partial state.  It is not reusable.
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (stream_.get() && next_state_ != STATE_DONE)
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stream_->Close(true /* not reusable */);
86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid HttpStreamFactoryImpl::Job::Start(Request* request) {
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(request);
90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  request_ = request;
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  StartInternal();
92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint HttpStreamFactoryImpl::Job::Preconnect(int num_streams) {
95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_GT(num_streams, 0);
96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  num_streams_ = num_streams;
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return StartInternal();
98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::RestartTunnelWithProxyAuth(
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const string16& username, const string16& password) {
102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(establishing_tunnel_);
103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  next_state_ = STATE_RESTART_TUNNEL_AUTH;
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  stream_.reset();
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return RunLoop(OK);
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
108dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenLoadState HttpStreamFactoryImpl::Job::GetLoadState() const {
109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  switch (next_state_) {
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case STATE_RESOLVE_PROXY_COMPLETE:
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case STATE_CREATE_STREAM_COMPLETE:
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return connection_->GetLoadState();
114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case STATE_INIT_CONNECTION_COMPLETE:
115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return LOAD_STATE_SENDING_REQUEST;
116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    default:
117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return LOAD_STATE_IDLE;
118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid HttpStreamFactoryImpl::Job::MarkAsAlternate(const GURL& original_url) {
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!original_url_.get());
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  original_url_.reset(new GURL(original_url));
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid HttpStreamFactoryImpl::Job::WaitFor(Job* job) {
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK_EQ(STATE_NONE, next_state_);
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK_EQ(STATE_NONE, job->next_state_);
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!blocking_job_);
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!job->dependent_job_);
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  blocking_job_ = job;
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  job->dependent_job_ = this;
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid HttpStreamFactoryImpl::Job::Resume(Job* job) {
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK_EQ(blocking_job_, job);
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  blocking_job_ = NULL;
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // We know we're blocked if the next_state_ is STATE_WAIT_FOR_JOB_COMPLETE.
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Unblock |this|.
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (next_state_ == STATE_WAIT_FOR_JOB_COMPLETE) {
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    MessageLoop::current()->PostTask(
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        FROM_HERE,
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        method_factory_.NewRunnableMethod(
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            &HttpStreamFactoryImpl::Job::OnIOComplete, OK));
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::Orphan(const Request* request) {
150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_EQ(request_, request);
151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  request_ = NULL;
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // We've been orphaned, but there's a job we're blocked on. Don't bother
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // racing, just cancel ourself.
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (blocking_job_) {
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK(blocking_job_->dependent_job_);
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    blocking_job_->dependent_job_ = NULL;
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    blocking_job_ = NULL;
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    stream_factory_->OnOrphanedJobComplete(this);
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool HttpStreamFactoryImpl::Job::was_npn_negotiated() const {
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return was_npn_negotiated_;
164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool HttpStreamFactoryImpl::Job::using_spdy() const {
167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return using_spdy_;
168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst SSLConfig& HttpStreamFactoryImpl::Job::ssl_config() const {
171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return ssl_config_;
172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst ProxyInfo& HttpStreamFactoryImpl::Job::proxy_info() const {
175dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return proxy_info_;
176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::GetSSLInfo() {
179dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(using_ssl_);
180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!establishing_tunnel_);
181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(connection_.get() && connection_->socket());
182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSLClientSocket* ssl_socket =
183dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      static_cast<SSLClientSocket*>(connection_->socket());
184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ssl_socket->GetSSLInfo(&ssl_info_);
185dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::OnStreamReadyCallback() {
188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(stream_.get());
189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!IsPreconnecting());
190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsOrphaned()) {
191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stream_factory_->OnOrphanedJobComplete(this);
192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    request_->Complete(was_npn_negotiated(),
194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                       using_spdy(),
195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                       net_log_.source());
196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    request_->OnStreamReady(this, ssl_config_, proxy_info_, stream_.release());
197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // |this| may be deleted after this call.
199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
201dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::OnSpdySessionReadyCallback() {
202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!stream_.get());
203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!IsPreconnecting());
204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(using_spdy());
205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(new_spdy_session_);
206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<SpdySession> spdy_session = new_spdy_session_;
207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  new_spdy_session_ = NULL;
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsOrphaned()) {
209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stream_factory_->OnSpdySessionReady(
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        spdy_session, spdy_session_direct_, ssl_config_, proxy_info_,
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        was_npn_negotiated(), using_spdy(), net_log_.source());
212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stream_factory_->OnOrphanedJobComplete(this);
213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    request_->OnSpdySessionReady(this, spdy_session, spdy_session_direct_);
215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // |this| may be deleted after this call.
217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::OnStreamFailedCallback(int result) {
220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!IsPreconnecting());
221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsOrphaned())
222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stream_factory_->OnOrphanedJobComplete(this);
223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  else
224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    request_->OnStreamFailed(this, result, ssl_config_);
225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // |this| may be deleted after this call.
226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::OnCertificateErrorCallback(
229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int result, const SSLInfo& ssl_info) {
230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!IsPreconnecting());
231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsOrphaned())
232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stream_factory_->OnOrphanedJobComplete(this);
233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  else
234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    request_->OnCertificateError(this, result, ssl_config_, ssl_info);
235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // |this| may be deleted after this call.
236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
237dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
238dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::OnNeedsProxyAuthCallback(
239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const HttpResponseInfo& response,
240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    HttpAuthController* auth_controller) {
241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!IsPreconnecting());
242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsOrphaned())
243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stream_factory_->OnOrphanedJobComplete(this);
244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  else
245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    request_->OnNeedsProxyAuth(
246dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        this, response, ssl_config_, proxy_info_, auth_controller);
247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // |this| may be deleted after this call.
248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::OnNeedsClientAuthCallback(
251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SSLCertRequestInfo* cert_info) {
252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!IsPreconnecting());
253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsOrphaned())
254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stream_factory_->OnOrphanedJobComplete(this);
255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  else
256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    request_->OnNeedsClientAuth(this, ssl_config_, cert_info);
257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // |this| may be deleted after this call.
258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
260dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::OnHttpsProxyTunnelResponseCallback(
261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const HttpResponseInfo& response_info,
262dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    HttpStream* stream) {
263dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!IsPreconnecting());
264dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsOrphaned())
265dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stream_factory_->OnOrphanedJobComplete(this);
266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  else
267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    request_->OnHttpsProxyTunnelResponse(
268dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        this, response_info, ssl_config_, proxy_info_, stream);
269dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // |this| may be deleted after this call.
270dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::OnPreconnectsComplete() {
273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!request_);
274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (new_spdy_session_) {
275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stream_factory_->OnSpdySessionReady(
276dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        new_spdy_session_, spdy_session_direct_, ssl_config_,
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        proxy_info_, was_npn_negotiated(), using_spdy(), net_log_.source());
278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  stream_factory_->OnPreconnectsComplete(this);
280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // |this| may be deleted after this call.
281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::OnIOComplete(int result) {
284dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  RunLoop(result);
285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
286dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::RunLoop(int result) {
288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  result = DoLoop(result);
289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
290dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (result == ERR_IO_PENDING)
291dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return result;
292dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsPreconnecting()) {
294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    MessageLoop::current()->PostTask(
295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        FROM_HERE,
296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        method_factory_.NewRunnableMethod(
297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            &HttpStreamFactoryImpl::Job::OnPreconnectsComplete));
298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return ERR_IO_PENDING;
299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsCertificateError(result)) {
302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Retrieve SSL information from the socket.
303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    GetSSLInfo();
304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    next_state_ = STATE_WAITING_USER_ACTION;
306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    MessageLoop::current()->PostTask(
307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        FROM_HERE,
308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        method_factory_.NewRunnableMethod(
309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            &HttpStreamFactoryImpl::Job::OnCertificateErrorCallback,
310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            result, ssl_info_));
311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return ERR_IO_PENDING;
312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  switch (result) {
315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_PROXY_AUTH_REQUESTED:
316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      {
317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK(connection_.get());
318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK(connection_->socket());
319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK(establishing_tunnel_);
320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        HttpProxyClientSocket* http_proxy_socket =
322dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            static_cast<HttpProxyClientSocket*>(connection_->socket());
323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        const HttpResponseInfo* tunnel_auth_response =
324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            http_proxy_socket->GetConnectResponseInfo();
325dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        next_state_ = STATE_WAITING_USER_ACTION;
327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        MessageLoop::current()->PostTask(
328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            FROM_HERE,
329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            method_factory_.NewRunnableMethod(
330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                &HttpStreamFactoryImpl::Job::OnNeedsProxyAuthCallback,
331dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                *tunnel_auth_response,
332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                http_proxy_socket->auth_controller()));
333dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return ERR_IO_PENDING;
335dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
336dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_SSL_CLIENT_AUTH_CERT_NEEDED:
337dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      MessageLoop::current()->PostTask(
338dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          FROM_HERE,
339dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          method_factory_.NewRunnableMethod(
340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              &HttpStreamFactoryImpl::Job::OnNeedsClientAuthCallback,
341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              connection_->ssl_error_response_info().cert_request_info));
342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return ERR_IO_PENDING;
343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_HTTPS_PROXY_TUNNEL_RESPONSE:
345dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      {
346dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK(connection_.get());
347dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK(connection_->socket());
348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK(establishing_tunnel_);
349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
350dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ProxyClientSocket* proxy_socket =
351dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            static_cast<ProxyClientSocket*>(connection_->socket());
352dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        MessageLoop::current()->PostTask(
353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            FROM_HERE,
354dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            method_factory_.NewRunnableMethod(
355dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                &HttpStreamFactoryImpl::Job::OnHttpsProxyTunnelResponseCallback,
356dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                *proxy_socket->GetConnectResponseInfo(),
357dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                proxy_socket->CreateConnectResponseStream()));
358dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return ERR_IO_PENDING;
359dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
360dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
361dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case OK:
362dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      next_state_ = STATE_DONE;
363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (new_spdy_session_) {
364dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        MessageLoop::current()->PostTask(
365dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            FROM_HERE,
366dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            method_factory_.NewRunnableMethod(
367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                &HttpStreamFactoryImpl::Job::OnSpdySessionReadyCallback));
368dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      } else {
369dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        MessageLoop::current()->PostTask(
370dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            FROM_HERE,
371dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            method_factory_.NewRunnableMethod(
372dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                &HttpStreamFactoryImpl::Job::OnStreamReadyCallback));
373dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
374dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return ERR_IO_PENDING;
375dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
376dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    default:
377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      MessageLoop::current()->PostTask(
378dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          FROM_HERE,
379dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          method_factory_.NewRunnableMethod(
380dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              &HttpStreamFactoryImpl::Job::OnStreamFailedCallback,
381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              result));
382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return ERR_IO_PENDING;
383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return result;
385dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
386dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
387dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::DoLoop(int result) {
388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_NE(next_state_, STATE_NONE);
389dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int rv = result;
390dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  do {
391dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    State state = next_state_;
392dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    next_state_ = STATE_NONE;
393dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    switch (state) {
394dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      case STATE_RESOLVE_PROXY:
395dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK_EQ(OK, rv);
396dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        rv = DoResolveProxy();
397dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        break;
398dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      case STATE_RESOLVE_PROXY_COMPLETE:
399dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        rv = DoResolveProxyComplete(rv);
400dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        break;
401ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      case STATE_WAIT_FOR_JOB:
402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        DCHECK_EQ(OK, rv);
403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        rv = DoWaitForJob();
404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        break;
405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      case STATE_WAIT_FOR_JOB_COMPLETE:
406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        rv = DoWaitForJobComplete(rv);
407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        break;
408dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      case STATE_INIT_CONNECTION:
409dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK_EQ(OK, rv);
410dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        rv = DoInitConnection();
411dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        break;
412dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      case STATE_INIT_CONNECTION_COMPLETE:
413dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        rv = DoInitConnectionComplete(rv);
414dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        break;
415dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      case STATE_WAITING_USER_ACTION:
416dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        rv = DoWaitingUserAction(rv);
417dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        break;
418dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      case STATE_RESTART_TUNNEL_AUTH:
419dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK_EQ(OK, rv);
420dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        rv = DoRestartTunnelAuth();
421dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        break;
422dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      case STATE_RESTART_TUNNEL_AUTH_COMPLETE:
423dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        rv = DoRestartTunnelAuthComplete(rv);
424dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        break;
425dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      case STATE_CREATE_STREAM:
426dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK_EQ(OK, rv);
427dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        rv = DoCreateStream();
428dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        break;
429dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      case STATE_CREATE_STREAM_COMPLETE:
430dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        rv = DoCreateStreamComplete(rv);
431dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        break;
432dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      default:
433dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        NOTREACHED() << "bad state";
434dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        rv = ERR_FAILED;
435dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        break;
436dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
437dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
438dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return rv;
439dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
440dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint HttpStreamFactoryImpl::Job::StartInternal() {
442dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CHECK_EQ(STATE_NONE, next_state_);
443dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_JOB,
444dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      make_scoped_refptr(new NetLogStringParameter(
445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          "url", request_info_.url.GetOrigin().spec())));
446dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  next_state_ = STATE_RESOLVE_PROXY;
447dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int rv = RunLoop(OK);
448dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_EQ(ERR_IO_PENDING, rv);
449dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return rv;
450dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
451dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
452dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::DoResolveProxy() {
453dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!pac_request_);
454dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
455dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
456dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  origin_ = HostPortPair(request_info_.url.HostNoBrackets(),
458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                         request_info_.url.EffectiveIntPort());
459dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
460dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (request_info_.load_flags & LOAD_BYPASS_PROXY) {
461dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    proxy_info_.UseDirect();
462dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return OK;
463dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
464dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
465dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return session_->proxy_service()->ResolveProxy(
466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      request_info_.url, &proxy_info_, &io_callback_, &pac_request_,
467dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      net_log_);
468dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
469dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
470dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
471dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  pac_request_ = NULL;
472dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
473ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (result == OK) {
474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Remove unsupported proxies from the list.
475ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    proxy_info_.RemoveProxiesWithoutScheme(
476ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ProxyServer::SCHEME_DIRECT |
477ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS |
478ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5);
479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (proxy_info_.is_empty()) {
481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // No proxies/direct to choose from. This happens when we don't support
482ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // any of the proxies in the returned list.
483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      result = ERR_NO_SUPPORTED_PROXIES;
484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
486dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (result != OK) {
488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (dependent_job_)
489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      dependent_job_->Resume(this);
490ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return result;
491dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
492dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
493ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (blocking_job_)
494ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    next_state_ = STATE_WAIT_FOR_JOB;
495ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  else
496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    next_state_ = STATE_INIT_CONNECTION;
497dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return OK;
498dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
499dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool HttpStreamFactoryImpl::Job::ShouldForceSpdySSL() const {
501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool rv = force_spdy_always_ && force_spdy_over_ssl_;
502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return rv && !HttpStreamFactory::HasSpdyExclusion(origin_);
503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
504dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
505ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool HttpStreamFactoryImpl::Job::ShouldForceSpdyWithoutSSL() const {
506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool rv = force_spdy_always_ && !force_spdy_over_ssl_;
507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return rv && !HttpStreamFactory::HasSpdyExclusion(origin_);
508dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
509dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint HttpStreamFactoryImpl::Job::DoWaitForJob() {
511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(blocking_job_);
512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  next_state_ = STATE_WAIT_FOR_JOB_COMPLETE;
513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return ERR_IO_PENDING;
514dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
515dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint HttpStreamFactoryImpl::Job::DoWaitForJobComplete(int result) {
517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!blocking_job_);
518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK_EQ(OK, result);
519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  next_state_ = STATE_INIT_CONNECTION;
520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return OK;
521dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
522dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
523dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::DoInitConnection() {
524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!blocking_job_);
525dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!connection_->is_initialized());
526dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(proxy_info_.proxy_server().is_valid());
527dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  next_state_ = STATE_INIT_CONNECTION_COMPLETE;
528dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  using_ssl_ = request_info_.url.SchemeIs("https") || ShouldForceSpdySSL();
530dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  using_spdy_ = false;
531dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Check first if we have a spdy session for this group.  If so, then go
533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // straight to using that.
534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  HostPortProxyPair spdy_session_key;
535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (IsHttpsProxyAndHttpUrl()) {
536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    spdy_session_key =
537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        HostPortProxyPair(proxy_info_.proxy_server().host_port_pair(),
538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          ProxyServer::Direct());
539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    spdy_session_key = HostPortProxyPair(origin_, proxy_info_.proxy_server());
541dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (session_->spdy_session_pool()->HasSession(spdy_session_key)) {
543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // If we're preconnecting, but we already have a SpdySession, we don't
544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // actually need to preconnect any sockets, so we're done.
545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (IsPreconnecting())
546dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return OK;
547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    using_spdy_ = true;
548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    next_state_ = STATE_CREATE_STREAM;
549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return OK;
550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) {
551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Update the spdy session key for the request that launched this job.
552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    request_->SetSpdySessionKey(spdy_session_key);
553dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
554dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // OK, there's no available SPDY session. Let |dependent_job_| resume if it's
556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // paused.
557dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (dependent_job_) {
559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    dependent_job_->Resume(this);
560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    dependent_job_ = NULL;
561dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
562dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
563ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (proxy_info_.is_http() || proxy_info_.is_https())
564ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    establishing_tunnel_ = using_ssl_;
565dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
566ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool want_spdy_over_npn = original_url_.get() ? true : false;
567dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
568ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SSLConfig ssl_config_for_proxy = ssl_config_;
569ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (proxy_info_.is_https()) {
570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    InitSSLConfig(proxy_info_.proxy_server().host_port_pair(),
571ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                  &ssl_config_for_proxy);
572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (using_ssl_) {
574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    InitSSLConfig(origin_, &ssl_config_);
575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
576dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
577dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsPreconnecting()) {
578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return ClientSocketPoolManager::PreconnectSocketsForHttpRequest(
579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        request_info_,
580ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        session_,
581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        proxy_info_,
582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ShouldForceSpdySSL(),
583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        want_spdy_over_npn,
584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ssl_config_,
585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ssl_config_for_proxy,
586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        net_log_,
587ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        num_streams_);
588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return ClientSocketPoolManager::InitSocketHandleForHttpRequest(
590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        request_info_,
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        session_,
592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        proxy_info_,
593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ShouldForceSpdySSL(),
594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        want_spdy_over_npn,
595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ssl_config_,
596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ssl_config_for_proxy,
597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        net_log_,
598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        connection_.get(),
599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        &io_callback_);
600dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
601dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
602dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
603dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
604dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsPreconnecting()) {
605dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK_EQ(OK, result);
606dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return OK;
607dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
608dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
609ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(willchan): Make this a bit more exact. Maybe there are recoverable
610ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // errors, such as ignoring certificate errors for Alternate-Protocol.
611ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (result < 0 && dependent_job_) {
612ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    dependent_job_->Resume(this);
613ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    dependent_job_ = NULL;
614ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
615ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
616dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // |result| may be the result of any of the stacked pools. The following
617dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // logic is used when determining how to interpret an error.
618dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // If |result| < 0:
619dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  //   and connection_->socket() != NULL, then the SSL handshake ran and it
620dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  //     is a potentially recoverable error.
621dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  //   and connection_->socket == NULL and connection_->is_ssl_error() is true,
622dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  //     then the SSL handshake ran with an unrecoverable error.
623dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  //   otherwise, the error came from one of the other pools.
624dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool ssl_started = using_ssl_ && (result == OK || connection_->socket() ||
625dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    connection_->is_ssl_error());
626dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
627dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (ssl_started && (result == OK || IsCertificateError(result))) {
628dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SSLClientSocket* ssl_socket =
629dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      static_cast<SSLClientSocket*>(connection_->socket());
630dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (ssl_socket->was_npn_negotiated()) {
631dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      was_npn_negotiated_ = true;
632dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (ssl_socket->was_spdy_negotiated())
633dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        SwitchToSpdyMode();
634dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
635dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (ShouldForceSpdySSL())
636dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      SwitchToSpdyMode();
637dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else if (proxy_info_.is_https() && connection_->socket() &&
638dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        result == OK) {
639dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    HttpProxyClientSocket* proxy_socket =
640dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      static_cast<HttpProxyClientSocket*>(connection_->socket());
641dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (proxy_socket->using_spdy()) {
642dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      was_npn_negotiated_ = true;
643dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      SwitchToSpdyMode();
644dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
645dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
646dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
647dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We may be using spdy without SSL
648dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (ShouldForceSpdyWithoutSSL())
649dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SwitchToSpdyMode();
650dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
651dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (result == ERR_PROXY_AUTH_REQUESTED ||
652dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
653dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(!ssl_started);
654dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an
655dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // SSL socket, but there was an error before that could happen.  This
656dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // puts the in progress HttpProxy socket into |connection_| in order to
657dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // complete the auth (or read the response body).  The tunnel restart code
658dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // is careful to remove it before returning control to the rest of this
659dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // class.
660dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    connection_.reset(connection_->release_pending_http_proxy_connection());
661dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return result;
662dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
663dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
664ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!ssl_started && result < 0 && original_url_.get()) {
665dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Mark the alternate protocol as broken and fallback.
666ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    session_->mutable_alternate_protocols()->MarkBrokenAlternateProtocolFor(
667ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        HostPortPair::FromURL(*original_url_));
668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return result;
669dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
670dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
671dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (result < 0 && !ssl_started)
672dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return ReconsiderProxyAfterError(result);
673dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  establishing_tunnel_ = false;
674dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
675dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (connection_->socket()) {
676dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LogHttpConnectedMetrics(*connection_);
677dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
678dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // We officially have a new connection.  Record the type.
679dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!connection_->is_reused()) {
680dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      ConnectionType type = using_spdy_ ? CONNECTION_SPDY : CONNECTION_HTTP;
681dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      UpdateConnectionTypeHistograms(type);
682dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
683dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
684dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
685dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Handle SSL errors below.
686dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (using_ssl_) {
687dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(ssl_started);
688dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (IsCertificateError(result)) {
689ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (using_spdy_ && original_url_.get() &&
690ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          original_url_->SchemeIs("http")) {
691dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        // We ignore certificate errors for http over spdy.
692dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        spdy_certificate_error_ = result;
693dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        result = OK;
694dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      } else {
695dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        result = HandleCertificateError(result);
696dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        if (result == OK && !connection_->socket()->IsConnectedAndIdle()) {
697dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          ReturnToStateInitConnection(true /* close connection */);
698dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          return result;
699dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        }
700dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
701dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
702dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (result < 0)
703dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return result;
704dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
705dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
706dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  next_state_ = STATE_CREATE_STREAM;
707dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return OK;
708dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
709dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
710dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) {
711dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // This state indicates that the stream request is in a partially
712dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // completed state, and we've called back to the delegate for more
713dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // information.
714dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
715dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We're always waiting here for the delegate to call us back.
716dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return ERR_IO_PENDING;
717dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
718dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
719dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::DoCreateStream() {
720dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  next_state_ = STATE_CREATE_STREAM_COMPLETE;
721dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
722dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We only set the socket motivation if we're the first to use
723dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // this socket.  Is there a race for two SPDY requests?  We really
724dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // need to plumb this through to the connect level.
725dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (connection_->socket() && !connection_->is_reused())
726dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SetSocketMotivation();
727dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
728dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const ProxyServer& proxy_server = proxy_info_.proxy_server();
729dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
730dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!using_spdy_) {
731dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) &&
732dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        request_info_.url.SchemeIs("http");
733dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stream_.reset(new HttpBasicStream(connection_.release(), NULL,
734dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                      using_proxy));
735dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return OK;
736dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
737dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
738dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CHECK(!stream_.get());
739dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
740dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool direct = true;
741dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SpdySessionPool* spdy_pool = session_->spdy_session_pool();
742dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<SpdySession> spdy_session;
743dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
744ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  HostPortProxyPair pair(origin_, proxy_server);
745dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (spdy_pool->HasSession(pair)) {
746dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // We have a SPDY session to the origin server.  This might be a direct
747dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // connection, or it might be a SPDY session through an HTTP or HTTPS proxy.
748dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    spdy_session = spdy_pool->Get(pair, net_log_);
749dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else if (IsHttpsProxyAndHttpUrl()) {
750dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // If we don't have a direct SPDY session, and we're using an HTTPS
751dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // proxy, then we might have a SPDY session to the proxy.
752dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    pair = HostPortProxyPair(proxy_server.host_port_pair(),
753dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                             ProxyServer::Direct());
754dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (spdy_pool->HasSession(pair)) {
755dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      spdy_session = spdy_pool->Get(pair, net_log_);
756dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
757dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    direct = false;
758dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
759dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
760dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (spdy_session.get()) {
761dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // We picked up an existing session, so we don't need our socket.
762dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (connection_->socket())
763dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      connection_->socket()->Disconnect();
764dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    connection_->Reset();
765dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
766dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // SPDY can be negotiated using the TLS next protocol negotiation (NPN)
767dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // extension, or just directly using SSL. Either way, |connection_| must
768dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // contain an SSLClientSocket.
769dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CHECK(connection_->socket());
770dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int error = spdy_pool->GetSpdySessionFromSocket(
771dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        pair, connection_.release(), net_log_, spdy_certificate_error_,
772dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        &spdy_session, using_ssl_);
773dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (error != OK)
774dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return error;
775dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    new_spdy_session_ = spdy_session;
776dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    spdy_session_direct_ = direct;
777dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return OK;
778dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
779dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
780dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (spdy_session->IsClosed())
781dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return ERR_CONNECTION_CLOSED;
782dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
783dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // TODO(willchan): Delete this code, because eventually, the
784dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // HttpStreamFactoryImpl will be creating all the SpdyHttpStreams, since it
785dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // will know when SpdySessions become available. The above HasSession() checks
786dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // will be able to be deleted too.
787dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
788dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool use_relative_url = direct || request_info_.url.SchemeIs("https");
789dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  stream_.reset(new SpdyHttpStream(spdy_session, use_relative_url));
790dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return OK;
791dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
792dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
793dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::DoCreateStreamComplete(int result) {
794dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (result < 0)
795dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return result;
796dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
797dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  next_state_ = STATE_NONE;
798dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return OK;
799dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
800dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
801dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::DoRestartTunnelAuth() {
802dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE;
803dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HttpProxyClientSocket* http_proxy_socket =
804dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      static_cast<HttpProxyClientSocket*>(connection_->socket());
805dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return http_proxy_socket->RestartWithAuth(&io_callback_);
806dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
807dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
808dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::DoRestartTunnelAuthComplete(int result) {
809dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (result == ERR_PROXY_AUTH_REQUESTED)
810dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return result;
811dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
812dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (result == OK) {
813dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Now that we've got the HttpProxyClientSocket connected.  We have
814dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // to release it as an idle socket into the pool and start the connection
815dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // process from the beginning.  Trying to pass it in with the
816dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // SSLSocketParams might cause a deadlock since params are dispatched
817dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // interchangeably.  This request won't necessarily get this http proxy
818dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // socket, but there will be forward progress.
819dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    establishing_tunnel_ = false;
820dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ReturnToStateInitConnection(false /* do not close connection */);
821dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return OK;
822dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
823dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
824dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return ReconsiderProxyAfterError(result);
825dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
826dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
827dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::ReturnToStateInitConnection(
828dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    bool close_connection) {
829dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (close_connection && connection_->socket())
830dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    connection_->socket()->Disconnect();
831dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  connection_->Reset();
832dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
833dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (request_)
834dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    request_->RemoveRequestFromSpdySessionRequestMap();
835dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
836dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  next_state_ = STATE_INIT_CONNECTION;
837dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
838dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
839dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::SetSocketMotivation() {
840dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED)
841dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    connection_->socket()->SetSubresourceSpeculation();
842dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED)
843dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    connection_->socket()->SetOmniboxSpeculation();
844dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED).
845dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
846dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
847dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool HttpStreamFactoryImpl::Job::IsHttpsProxyAndHttpUrl() {
848ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!proxy_info_.is_https())
849ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
850ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (original_url_.get()) {
851ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // We currently only support Alternate-Protocol where the original scheme
852ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // is http.
853ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK(original_url_->SchemeIs("http"));
854ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return original_url_->SchemeIs("http");
855ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
856ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return request_info_.url.SchemeIs("http");
857dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
858dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
859ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Sets several fields of ssl_config for the given origin_server based on the
860ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// proxy info and other factors.
861ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid HttpStreamFactoryImpl::Job::InitSSLConfig(
862ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const HostPortPair& origin_server,
863ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SSLConfig* ssl_config) const {
864ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (stream_factory_->IsTLSIntolerantServer(origin_server)) {
865dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: "
866ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        << origin_server.ToString();
867ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ssl_config->ssl3_fallback = true;
868ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ssl_config->tls1_enabled = false;
869dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
870dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
871ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (proxy_info_.is_https() && ssl_config->send_client_cert) {
872dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // When connecting through an HTTPS proxy, disable TLS False Start so
873dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // that client authentication errors can be distinguished between those
874dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // originating from the proxy server (ERR_PROXY_CONNECTION_FAILED) and
875dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // those originating from the endpoint (ERR_SSL_PROTOCOL_ERROR /
876dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // ERR_BAD_SSL_CLIENT_AUTH_CERT).
877dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // TODO(rch): This assumes that the HTTPS proxy will only request a
878dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // client certificate during the initial handshake.
879dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // http://crbug.com/59292
880ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ssl_config->false_start_enabled = false;
881dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
882dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
883dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback",
884ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            static_cast<int>(ssl_config->ssl3_fallback), 2);
885dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
886dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (request_info_.load_flags & LOAD_VERIFY_EV_CERT)
887ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ssl_config->verify_ev_cert = true;
888dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
889dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
890dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
891dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) {
892dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!pac_request_);
893dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
894dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // A failure to resolve the hostname or any error related to establishing a
895dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // TCP connection could be grounds for trying a new proxy configuration.
896dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  //
897dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Why do this when a hostname cannot be resolved?  Some URLs only make sense
898dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // to proxy servers.  The hostname in those URLs might fail to resolve if we
899dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // are still using a non-proxy config.  We need to check if a proxy config
900dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // now exists that corresponds to a proxy server that could load the URL.
901dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  //
902dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  switch (error) {
903dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_PROXY_CONNECTION_FAILED:
904dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_NAME_NOT_RESOLVED:
905dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_INTERNET_DISCONNECTED:
906dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_ADDRESS_UNREACHABLE:
907dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_CONNECTION_CLOSED:
908dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_CONNECTION_RESET:
909dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_CONNECTION_REFUSED:
910dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_CONNECTION_ABORTED:
911dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_TIMED_OUT:
912dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_TUNNEL_CONNECTION_FAILED:
913dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_SOCKS_CONNECTION_FAILED:
914dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
915dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ERR_SOCKS_CONNECTION_HOST_UNREACHABLE:
916dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // Remap the SOCKS-specific "host unreachable" error to a more
917dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // generic error code (this way consumers like the link doctor
918dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // know to substitute their error page).
919dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      //
920dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // Note that if the host resolving was done by the SOCSK5 proxy, we can't
921dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // differentiate between a proxy-side "host not found" versus a proxy-side
922dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // "address unreachable" error, and will report both of these failures as
923dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // ERR_ADDRESS_UNREACHABLE.
924dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return ERR_ADDRESS_UNREACHABLE;
925dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    default:
926dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return error;
927dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
928dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
929dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (request_info_.load_flags & LOAD_BYPASS_PROXY) {
930dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return error;
931dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
932dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
933dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (proxy_info_.is_https() && ssl_config_.send_client_cert) {
934dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    session_->ssl_client_auth_cache()->Remove(
935dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        proxy_info_.proxy_server().host_port_pair().ToString());
936dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
937dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
938dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int rv = session_->proxy_service()->ReconsiderProxyAfterError(
939dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      request_info_.url, &proxy_info_, &io_callback_, &pac_request_,
940dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      net_log_);
941dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (rv == OK || rv == ERR_IO_PENDING) {
942dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // If the error was during connection setup, there is no socket to
943dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // disconnect.
944dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (connection_->socket())
945dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      connection_->socket()->Disconnect();
946dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    connection_->Reset();
947dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (request_)
948dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      request_->RemoveRequestFromSpdySessionRequestMap();
949dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
950dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
951dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // If ReconsiderProxyAfterError() failed synchronously, it means
952dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // there was nothing left to fall-back to, so fail the transaction
953dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // with the last connection error we got.
954dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // TODO(eroman): This is a confusing contract, make it more obvious.
955dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    rv = error;
956dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
957dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
958dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return rv;
959dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
960dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
961dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Job::HandleCertificateError(int error) {
962dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(using_ssl_);
963dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(IsCertificateError(error));
964dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
965dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSLClientSocket* ssl_socket =
966dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      static_cast<SSLClientSocket*>(connection_->socket());
967dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ssl_socket->GetSSLInfo(&ssl_info_);
968dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
969dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Add the bad certificate to the set of allowed certificates in the
970ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // SSL config object. This data structure will be consulted after calling
971dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // RestartIgnoringLastError(). And the user will be asked interactively
972dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // before RestartIgnoringLastError() is ever called.
973dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSLConfig::CertAndStatus bad_cert;
974dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bad_cert.cert = ssl_info_.cert;
975dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bad_cert.cert_status = ssl_info_.cert_status;
976dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ssl_config_.allowed_bad_certs.push_back(bad_cert);
977dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
978dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int load_flags = request_info_.load_flags;
979dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (HttpStreamFactory::ignore_certificate_errors())
980dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS;
981dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (ssl_socket->IgnoreCertError(error, load_flags))
982dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return OK;
983dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return error;
984dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
985dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
986dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::SwitchToSpdyMode() {
987dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (HttpStreamFactory::spdy_enabled())
988dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    using_spdy_ = true;
989dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
990dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
991dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static
992dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Job::LogHttpConnectedMetrics(
993dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const ClientSocketHandle& handle) {
994dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  UMA_HISTOGRAM_ENUMERATION("Net.HttpSocketType", handle.reuse_type(),
995dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            ClientSocketHandle::NUM_TYPES);
996dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
997dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  switch (handle.reuse_type()) {
998dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ClientSocketHandle::UNUSED:
999dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      UMA_HISTOGRAM_CUSTOM_TIMES("Net.HttpConnectionLatency",
1000dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 handle.setup_time(),
1001dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 base::TimeDelta::FromMilliseconds(1),
1002dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 base::TimeDelta::FromMinutes(10),
1003dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 100);
1004dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
1005dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ClientSocketHandle::UNUSED_IDLE:
1006dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      UMA_HISTOGRAM_CUSTOM_TIMES("Net.SocketIdleTimeBeforeNextUse_UnusedSocket",
1007dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 handle.idle_time(),
1008dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 base::TimeDelta::FromMilliseconds(1),
1009dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 base::TimeDelta::FromMinutes(6),
1010dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 100);
1011dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
1012dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case ClientSocketHandle::REUSED_IDLE:
1013dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      UMA_HISTOGRAM_CUSTOM_TIMES("Net.SocketIdleTimeBeforeNextUse_ReusedSocket",
1014dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 handle.idle_time(),
1015dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 base::TimeDelta::FromMilliseconds(1),
1016dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 base::TimeDelta::FromMinutes(6),
1017dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 100);
1018dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
1019dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    default:
1020dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NOTREACHED();
1021dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
1022dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1023dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1024dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1025dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool HttpStreamFactoryImpl::Job::IsPreconnecting() const {
1026dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_GE(num_streams_, 0);
1027dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return num_streams_ > 0;
1028dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1029dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1030dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool HttpStreamFactoryImpl::Job::IsOrphaned() const {
1031dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return !IsPreconnecting() && !request_;
1032dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1033dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1034dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}  // namespace net
1035