Home | History | Annotate | Download | only in http
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/http/http_stream_factory_impl_job.h"
      6 
      7 #include <algorithm>
      8 #include <string>
      9 
     10 #include "base/bind.h"
     11 #include "base/bind_helpers.h"
     12 #include "base/logging.h"
     13 #include "base/stl_util.h"
     14 #include "base/strings/string_util.h"
     15 #include "base/strings/stringprintf.h"
     16 #include "base/values.h"
     17 #include "build/build_config.h"
     18 #include "net/base/connection_type_histograms.h"
     19 #include "net/base/net_log.h"
     20 #include "net/base/net_util.h"
     21 #include "net/http/http_basic_stream.h"
     22 #include "net/http/http_network_session.h"
     23 #include "net/http/http_pipelined_connection.h"
     24 #include "net/http/http_pipelined_host.h"
     25 #include "net/http/http_pipelined_host_pool.h"
     26 #include "net/http/http_pipelined_stream.h"
     27 #include "net/http/http_proxy_client_socket.h"
     28 #include "net/http/http_proxy_client_socket_pool.h"
     29 #include "net/http/http_request_info.h"
     30 #include "net/http/http_server_properties.h"
     31 #include "net/http/http_stream_factory.h"
     32 #include "net/http/http_stream_factory_impl_request.h"
     33 #include "net/quic/quic_http_stream.h"
     34 #include "net/socket/client_socket_handle.h"
     35 #include "net/socket/client_socket_pool.h"
     36 #include "net/socket/client_socket_pool_manager.h"
     37 #include "net/socket/socks_client_socket_pool.h"
     38 #include "net/socket/ssl_client_socket.h"
     39 #include "net/socket/ssl_client_socket_pool.h"
     40 #include "net/spdy/spdy_http_stream.h"
     41 #include "net/spdy/spdy_session.h"
     42 #include "net/spdy/spdy_session_pool.h"
     43 #include "net/ssl/ssl_cert_request_info.h"
     44 
     45 namespace net {
     46 
     47 // Returns parameters associated with the start of a HTTP stream job.
     48 base::Value* NetLogHttpStreamJobCallback(const GURL* original_url,
     49                                          const GURL* url,
     50                                          RequestPriority priority,
     51                                          NetLog::LogLevel /* log_level */) {
     52   base::DictionaryValue* dict = new base::DictionaryValue();
     53   dict->SetString("original_url", original_url->GetOrigin().spec());
     54   dict->SetString("url", url->GetOrigin().spec());
     55   dict->SetInteger("priority", priority);
     56   return dict;
     57 }
     58 
     59 // Returns parameters associated with the Proto (with NPN negotiation) of a HTTP
     60 // stream.
     61 base::Value* NetLogHttpStreamProtoCallback(
     62     const SSLClientSocket::NextProtoStatus status,
     63     const std::string* proto,
     64     const std::string* server_protos,
     65     NetLog::LogLevel /* log_level */) {
     66   base::DictionaryValue* dict = new base::DictionaryValue();
     67 
     68   dict->SetString("next_proto_status",
     69                   SSLClientSocket::NextProtoStatusToString(status));
     70   dict->SetString("proto", *proto);
     71   dict->SetString("server_protos",
     72                   SSLClientSocket::ServerProtosToString(*server_protos));
     73   return dict;
     74 }
     75 
     76 HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory,
     77                                 HttpNetworkSession* session,
     78                                 const HttpRequestInfo& request_info,
     79                                 RequestPriority priority,
     80                                 const SSLConfig& server_ssl_config,
     81                                 const SSLConfig& proxy_ssl_config,
     82                                 NetLog* net_log)
     83     : request_(NULL),
     84       request_info_(request_info),
     85       priority_(priority),
     86       server_ssl_config_(server_ssl_config),
     87       proxy_ssl_config_(proxy_ssl_config),
     88       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_HTTP_STREAM_JOB)),
     89       io_callback_(base::Bind(&Job::OnIOComplete, base::Unretained(this))),
     90       connection_(new ClientSocketHandle),
     91       session_(session),
     92       stream_factory_(stream_factory),
     93       next_state_(STATE_NONE),
     94       pac_request_(NULL),
     95       blocking_job_(NULL),
     96       waiting_job_(NULL),
     97       using_ssl_(false),
     98       using_spdy_(false),
     99       using_quic_(false),
    100       quic_request_(session_->quic_stream_factory()),
    101       force_spdy_always_(HttpStreamFactory::force_spdy_always()),
    102       force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()),
    103       spdy_certificate_error_(OK),
    104       establishing_tunnel_(false),
    105       was_npn_negotiated_(false),
    106       protocol_negotiated_(kProtoUnknown),
    107       num_streams_(0),
    108       spdy_session_direct_(false),
    109       existing_available_pipeline_(false),
    110       ptr_factory_(this) {
    111   DCHECK(stream_factory);
    112   DCHECK(session);
    113 }
    114 
    115 HttpStreamFactoryImpl::Job::~Job() {
    116   net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_JOB);
    117 
    118   // When we're in a partially constructed state, waiting for the user to
    119   // provide certificate handling information or authentication, we can't reuse
    120   // this stream at all.
    121   if (next_state_ == STATE_WAITING_USER_ACTION) {
    122     connection_->socket()->Disconnect();
    123     connection_.reset();
    124   }
    125 
    126   if (pac_request_)
    127     session_->proxy_service()->CancelPacRequest(pac_request_);
    128 
    129   // The stream could be in a partial state.  It is not reusable.
    130   if (stream_.get() && next_state_ != STATE_DONE)
    131     stream_->Close(true /* not reusable */);
    132 }
    133 
    134 void HttpStreamFactoryImpl::Job::Start(Request* request) {
    135   DCHECK(request);
    136   request_ = request;
    137   StartInternal();
    138 }
    139 
    140 int HttpStreamFactoryImpl::Job::Preconnect(int num_streams) {
    141   DCHECK_GT(num_streams, 0);
    142   HostPortPair origin_server =
    143       HostPortPair(request_info_.url.HostNoBrackets(),
    144                    request_info_.url.EffectiveIntPort());
    145   base::WeakPtr<HttpServerProperties> http_server_properties =
    146       session_->http_server_properties();
    147   if (http_server_properties &&
    148       http_server_properties->SupportsSpdy(origin_server)) {
    149     num_streams_ = 1;
    150   } else {
    151     num_streams_ = num_streams;
    152   }
    153   return StartInternal();
    154 }
    155 
    156 int HttpStreamFactoryImpl::Job::RestartTunnelWithProxyAuth(
    157     const AuthCredentials& credentials) {
    158   DCHECK(establishing_tunnel_);
    159   next_state_ = STATE_RESTART_TUNNEL_AUTH;
    160   stream_.reset();
    161   return RunLoop(OK);
    162 }
    163 
    164 LoadState HttpStreamFactoryImpl::Job::GetLoadState() const {
    165   switch (next_state_) {
    166     case STATE_RESOLVE_PROXY_COMPLETE:
    167       return session_->proxy_service()->GetLoadState(pac_request_);
    168     case STATE_INIT_CONNECTION_COMPLETE:
    169     case STATE_CREATE_STREAM_COMPLETE:
    170       return using_quic_ ? LOAD_STATE_CONNECTING : connection_->GetLoadState();
    171     default:
    172       return LOAD_STATE_IDLE;
    173   }
    174 }
    175 
    176 void HttpStreamFactoryImpl::Job::MarkAsAlternate(
    177     const GURL& original_url,
    178     PortAlternateProtocolPair alternate) {
    179   DCHECK(!original_url_.get());
    180   original_url_.reset(new GURL(original_url));
    181   if (alternate.protocol == QUIC) {
    182     DCHECK(session_->params().enable_quic);
    183     using_quic_ = true;
    184   }
    185 }
    186 
    187 void HttpStreamFactoryImpl::Job::WaitFor(Job* job) {
    188   DCHECK_EQ(STATE_NONE, next_state_);
    189   DCHECK_EQ(STATE_NONE, job->next_state_);
    190   DCHECK(!blocking_job_);
    191   DCHECK(!job->waiting_job_);
    192   blocking_job_ = job;
    193   job->waiting_job_ = this;
    194 }
    195 
    196 void HttpStreamFactoryImpl::Job::Resume(Job* job) {
    197   DCHECK_EQ(blocking_job_, job);
    198   blocking_job_ = NULL;
    199 
    200   // We know we're blocked if the next_state_ is STATE_WAIT_FOR_JOB_COMPLETE.
    201   // Unblock |this|.
    202   if (next_state_ == STATE_WAIT_FOR_JOB_COMPLETE) {
    203     base::MessageLoop::current()->PostTask(
    204         FROM_HERE,
    205         base::Bind(&HttpStreamFactoryImpl::Job::OnIOComplete,
    206                    ptr_factory_.GetWeakPtr(), OK));
    207   }
    208 }
    209 
    210 void HttpStreamFactoryImpl::Job::Orphan(const Request* request) {
    211   DCHECK_EQ(request_, request);
    212   request_ = NULL;
    213   if (blocking_job_) {
    214     // We've been orphaned, but there's a job we're blocked on. Don't bother
    215     // racing, just cancel ourself.
    216     DCHECK(blocking_job_->waiting_job_);
    217     blocking_job_->waiting_job_ = NULL;
    218     blocking_job_ = NULL;
    219     if (stream_factory_->for_websockets_ &&
    220         connection_ && connection_->socket())
    221       connection_->socket()->Disconnect();
    222     stream_factory_->OnOrphanedJobComplete(this);
    223   } else if (stream_factory_->for_websockets_) {
    224     // We cancel this job because WebSocketStream can't be created
    225     // without a WebSocketStreamBase::Factory which is stored in Request class
    226     // and isn't accessible from this job.
    227     if (connection_ && connection_->socket())
    228       connection_->socket()->Disconnect();
    229     stream_factory_->OnOrphanedJobComplete(this);
    230   }
    231 }
    232 
    233 bool HttpStreamFactoryImpl::Job::was_npn_negotiated() const {
    234   return was_npn_negotiated_;
    235 }
    236 
    237 NextProto HttpStreamFactoryImpl::Job::protocol_negotiated()
    238     const {
    239   return protocol_negotiated_;
    240 }
    241 
    242 bool HttpStreamFactoryImpl::Job::using_spdy() const {
    243   return using_spdy_;
    244 }
    245 
    246 const SSLConfig& HttpStreamFactoryImpl::Job::server_ssl_config() const {
    247   return server_ssl_config_;
    248 }
    249 
    250 const SSLConfig& HttpStreamFactoryImpl::Job::proxy_ssl_config() const {
    251   return proxy_ssl_config_;
    252 }
    253 
    254 const ProxyInfo& HttpStreamFactoryImpl::Job::proxy_info() const {
    255   return proxy_info_;
    256 }
    257 
    258 void HttpStreamFactoryImpl::Job::GetSSLInfo() {
    259   DCHECK(using_ssl_);
    260   DCHECK(!establishing_tunnel_);
    261   DCHECK(connection_.get() && connection_->socket());
    262   SSLClientSocket* ssl_socket =
    263       static_cast<SSLClientSocket*>(connection_->socket());
    264   ssl_socket->GetSSLInfo(&ssl_info_);
    265 }
    266 
    267 SpdySessionKey HttpStreamFactoryImpl::Job::GetSpdySessionKey() const {
    268   // In the case that we're using an HTTPS proxy for an HTTP url,
    269   // we look for a SPDY session *to* the proxy, instead of to the
    270   // origin server.
    271   PrivacyMode privacy_mode = request_info_.privacy_mode;
    272   if (IsHttpsProxyAndHttpUrl()) {
    273     return SpdySessionKey(proxy_info_.proxy_server().host_port_pair(),
    274                           ProxyServer::Direct(),
    275                           privacy_mode);
    276   } else {
    277     return SpdySessionKey(origin_,
    278                           proxy_info_.proxy_server(),
    279                           privacy_mode);
    280   }
    281 }
    282 
    283 bool HttpStreamFactoryImpl::Job::CanUseExistingSpdySession() const {
    284   // We need to make sure that if a spdy session was created for
    285   // https://somehost/ that we don't use that session for http://somehost:443/.
    286   // The only time we can use an existing session is if the request URL is
    287   // https (the normal case) or if we're connection to a SPDY proxy, or
    288   // if we're running with force_spdy_always_.  crbug.com/133176
    289   return request_info_.url.SchemeIs("https") ||
    290          request_info_.url.SchemeIs("wss") ||
    291          proxy_info_.proxy_server().is_https() ||
    292          force_spdy_always_;
    293 }
    294 
    295 void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() {
    296   DCHECK(stream_.get());
    297   DCHECK(!IsPreconnecting());
    298   DCHECK(!stream_factory_->for_websockets_);
    299   if (IsOrphaned()) {
    300     stream_factory_->OnOrphanedJobComplete(this);
    301   } else {
    302     request_->Complete(was_npn_negotiated(),
    303                        protocol_negotiated(),
    304                        using_spdy(),
    305                        net_log_);
    306     request_->OnStreamReady(this, server_ssl_config_, proxy_info_,
    307                             stream_.release());
    308   }
    309   // |this| may be deleted after this call.
    310 }
    311 
    312 void HttpStreamFactoryImpl::Job::OnWebSocketStreamReadyCallback() {
    313   DCHECK(websocket_stream_);
    314   DCHECK(!IsPreconnecting());
    315   DCHECK(stream_factory_->for_websockets_);
    316   // An orphaned WebSocket job will be closed immediately and
    317   // never be ready.
    318   DCHECK(!IsOrphaned());
    319   request_->Complete(was_npn_negotiated(),
    320                      protocol_negotiated(),
    321                      using_spdy(),
    322                      net_log_);
    323   request_->OnWebSocketStreamReady(this,
    324                                    server_ssl_config_,
    325                                    proxy_info_,
    326                                    websocket_stream_.release());
    327   // |this| may be deleted after this call.
    328 }
    329 
    330 void HttpStreamFactoryImpl::Job::OnNewSpdySessionReadyCallback() {
    331   DCHECK(!stream_.get());
    332   DCHECK(!IsPreconnecting());
    333   DCHECK(using_spdy());
    334   if (!new_spdy_session_)
    335     return;
    336   base::WeakPtr<SpdySession> spdy_session = new_spdy_session_;
    337   new_spdy_session_.reset();
    338   if (IsOrphaned()) {
    339     stream_factory_->OnNewSpdySessionReady(
    340         spdy_session, spdy_session_direct_, server_ssl_config_, proxy_info_,
    341         was_npn_negotiated(), protocol_negotiated(), using_spdy(), net_log_);
    342     stream_factory_->OnOrphanedJobComplete(this);
    343   } else {
    344     request_->OnNewSpdySessionReady(this, spdy_session, spdy_session_direct_);
    345   }
    346   // |this| may be deleted after this call.
    347 }
    348 
    349 void HttpStreamFactoryImpl::Job::OnStreamFailedCallback(int result) {
    350   DCHECK(!IsPreconnecting());
    351   if (IsOrphaned())
    352     stream_factory_->OnOrphanedJobComplete(this);
    353   else
    354     request_->OnStreamFailed(this, result, server_ssl_config_);
    355   // |this| may be deleted after this call.
    356 }
    357 
    358 void HttpStreamFactoryImpl::Job::OnCertificateErrorCallback(
    359     int result, const SSLInfo& ssl_info) {
    360   DCHECK(!IsPreconnecting());
    361   if (IsOrphaned())
    362     stream_factory_->OnOrphanedJobComplete(this);
    363   else
    364     request_->OnCertificateError(this, result, server_ssl_config_, ssl_info);
    365   // |this| may be deleted after this call.
    366 }
    367 
    368 void HttpStreamFactoryImpl::Job::OnNeedsProxyAuthCallback(
    369     const HttpResponseInfo& response,
    370     HttpAuthController* auth_controller) {
    371   DCHECK(!IsPreconnecting());
    372   if (IsOrphaned())
    373     stream_factory_->OnOrphanedJobComplete(this);
    374   else
    375     request_->OnNeedsProxyAuth(
    376         this, response, server_ssl_config_, proxy_info_, auth_controller);
    377   // |this| may be deleted after this call.
    378 }
    379 
    380 void HttpStreamFactoryImpl::Job::OnNeedsClientAuthCallback(
    381     SSLCertRequestInfo* cert_info) {
    382   DCHECK(!IsPreconnecting());
    383   if (IsOrphaned())
    384     stream_factory_->OnOrphanedJobComplete(this);
    385   else
    386     request_->OnNeedsClientAuth(this, server_ssl_config_, cert_info);
    387   // |this| may be deleted after this call.
    388 }
    389 
    390 void HttpStreamFactoryImpl::Job::OnHttpsProxyTunnelResponseCallback(
    391     const HttpResponseInfo& response_info,
    392     HttpStream* stream) {
    393   DCHECK(!IsPreconnecting());
    394   if (IsOrphaned())
    395     stream_factory_->OnOrphanedJobComplete(this);
    396   else
    397     request_->OnHttpsProxyTunnelResponse(
    398         this, response_info, server_ssl_config_, proxy_info_, stream);
    399   // |this| may be deleted after this call.
    400 }
    401 
    402 void HttpStreamFactoryImpl::Job::OnPreconnectsComplete() {
    403   DCHECK(!request_);
    404   if (new_spdy_session_.get()) {
    405     stream_factory_->OnNewSpdySessionReady(new_spdy_session_,
    406                                            spdy_session_direct_,
    407                                            server_ssl_config_,
    408                                            proxy_info_,
    409                                            was_npn_negotiated(),
    410                                            protocol_negotiated(),
    411                                            using_spdy(),
    412                                            net_log_);
    413   }
    414   stream_factory_->OnPreconnectsComplete(this);
    415   // |this| may be deleted after this call.
    416 }
    417 
    418 // static
    419 int HttpStreamFactoryImpl::Job::OnHostResolution(
    420     SpdySessionPool* spdy_session_pool,
    421     const SpdySessionKey& spdy_session_key,
    422     const AddressList& addresses,
    423     const BoundNetLog& net_log) {
    424   // It is OK to dereference spdy_session_pool, because the
    425   // ClientSocketPoolManager will be destroyed in the same callback that
    426   // destroys the SpdySessionPool.
    427   return
    428       spdy_session_pool->FindAvailableSession(spdy_session_key, net_log) ?
    429       ERR_SPDY_SESSION_ALREADY_EXISTS : OK;
    430 }
    431 
    432 void HttpStreamFactoryImpl::Job::OnIOComplete(int result) {
    433   RunLoop(result);
    434 }
    435 
    436 int HttpStreamFactoryImpl::Job::RunLoop(int result) {
    437   result = DoLoop(result);
    438 
    439   if (result == ERR_IO_PENDING)
    440     return result;
    441 
    442   // If there was an error, we should have already resumed the |waiting_job_|,
    443   // if there was one.
    444   DCHECK(result == OK || waiting_job_ == NULL);
    445 
    446   if (IsPreconnecting()) {
    447     base::MessageLoop::current()->PostTask(
    448         FROM_HERE,
    449         base::Bind(
    450             &HttpStreamFactoryImpl::Job::OnPreconnectsComplete,
    451             ptr_factory_.GetWeakPtr()));
    452     return ERR_IO_PENDING;
    453   }
    454 
    455   if (IsCertificateError(result)) {
    456     // Retrieve SSL information from the socket.
    457     GetSSLInfo();
    458 
    459     next_state_ = STATE_WAITING_USER_ACTION;
    460     base::MessageLoop::current()->PostTask(
    461         FROM_HERE,
    462         base::Bind(
    463             &HttpStreamFactoryImpl::Job::OnCertificateErrorCallback,
    464             ptr_factory_.GetWeakPtr(),
    465             result, ssl_info_));
    466     return ERR_IO_PENDING;
    467   }
    468 
    469   switch (result) {
    470     case ERR_PROXY_AUTH_REQUESTED:
    471       {
    472         DCHECK(connection_.get());
    473         DCHECK(connection_->socket());
    474         DCHECK(establishing_tunnel_);
    475 
    476         ProxyClientSocket* proxy_socket =
    477             static_cast<ProxyClientSocket*>(connection_->socket());
    478         const HttpResponseInfo* tunnel_auth_response =
    479             proxy_socket->GetConnectResponseInfo();
    480 
    481         next_state_ = STATE_WAITING_USER_ACTION;
    482         base::MessageLoop::current()->PostTask(
    483             FROM_HERE,
    484             base::Bind(
    485                 &Job::OnNeedsProxyAuthCallback,
    486                 ptr_factory_.GetWeakPtr(),
    487                 *tunnel_auth_response,
    488                 proxy_socket->GetAuthController()));
    489       }
    490       return ERR_IO_PENDING;
    491 
    492     case ERR_SSL_CLIENT_AUTH_CERT_NEEDED:
    493       base::MessageLoop::current()->PostTask(
    494           FROM_HERE,
    495           base::Bind(
    496               &Job::OnNeedsClientAuthCallback,
    497               ptr_factory_.GetWeakPtr(),
    498               connection_->ssl_error_response_info().cert_request_info));
    499       return ERR_IO_PENDING;
    500 
    501     case ERR_HTTPS_PROXY_TUNNEL_RESPONSE:
    502       {
    503         DCHECK(connection_.get());
    504         DCHECK(connection_->socket());
    505         DCHECK(establishing_tunnel_);
    506 
    507         ProxyClientSocket* proxy_socket =
    508             static_cast<ProxyClientSocket*>(connection_->socket());
    509         base::MessageLoop::current()->PostTask(
    510             FROM_HERE,
    511             base::Bind(
    512                 &Job::OnHttpsProxyTunnelResponseCallback,
    513                 ptr_factory_.GetWeakPtr(),
    514                 *proxy_socket->GetConnectResponseInfo(),
    515                 proxy_socket->CreateConnectResponseStream()));
    516         return ERR_IO_PENDING;
    517       }
    518 
    519     case OK:
    520       next_state_ = STATE_DONE;
    521       if (new_spdy_session_.get()) {
    522         base::MessageLoop::current()->PostTask(
    523             FROM_HERE,
    524             base::Bind(&Job::OnNewSpdySessionReadyCallback,
    525                        ptr_factory_.GetWeakPtr()));
    526       } else if (stream_factory_->for_websockets_) {
    527         DCHECK(websocket_stream_);
    528         base::MessageLoop::current()->PostTask(
    529             FROM_HERE,
    530             base::Bind(
    531                 &Job::OnWebSocketStreamReadyCallback,
    532                 ptr_factory_.GetWeakPtr()));
    533       } else {
    534         DCHECK(stream_.get());
    535         base::MessageLoop::current()->PostTask(
    536             FROM_HERE,
    537             base::Bind(
    538                 &Job::OnStreamReadyCallback,
    539                 ptr_factory_.GetWeakPtr()));
    540       }
    541       return ERR_IO_PENDING;
    542 
    543     default:
    544       base::MessageLoop::current()->PostTask(
    545           FROM_HERE,
    546           base::Bind(
    547               &Job::OnStreamFailedCallback,
    548               ptr_factory_.GetWeakPtr(),
    549               result));
    550       return ERR_IO_PENDING;
    551   }
    552   return result;
    553 }
    554 
    555 int HttpStreamFactoryImpl::Job::DoLoop(int result) {
    556   DCHECK_NE(next_state_, STATE_NONE);
    557   int rv = result;
    558   do {
    559     State state = next_state_;
    560     next_state_ = STATE_NONE;
    561     switch (state) {
    562       case STATE_START:
    563         DCHECK_EQ(OK, rv);
    564         rv = DoStart();
    565         break;
    566       case STATE_RESOLVE_PROXY:
    567         DCHECK_EQ(OK, rv);
    568         rv = DoResolveProxy();
    569         break;
    570       case STATE_RESOLVE_PROXY_COMPLETE:
    571         rv = DoResolveProxyComplete(rv);
    572         break;
    573       case STATE_WAIT_FOR_JOB:
    574         DCHECK_EQ(OK, rv);
    575         rv = DoWaitForJob();
    576         break;
    577       case STATE_WAIT_FOR_JOB_COMPLETE:
    578         rv = DoWaitForJobComplete(rv);
    579         break;
    580       case STATE_INIT_CONNECTION:
    581         DCHECK_EQ(OK, rv);
    582         rv = DoInitConnection();
    583         break;
    584       case STATE_INIT_CONNECTION_COMPLETE:
    585         rv = DoInitConnectionComplete(rv);
    586         break;
    587       case STATE_WAITING_USER_ACTION:
    588         rv = DoWaitingUserAction(rv);
    589         break;
    590       case STATE_RESTART_TUNNEL_AUTH:
    591         DCHECK_EQ(OK, rv);
    592         rv = DoRestartTunnelAuth();
    593         break;
    594       case STATE_RESTART_TUNNEL_AUTH_COMPLETE:
    595         rv = DoRestartTunnelAuthComplete(rv);
    596         break;
    597       case STATE_CREATE_STREAM:
    598         DCHECK_EQ(OK, rv);
    599         rv = DoCreateStream();
    600         break;
    601       case STATE_CREATE_STREAM_COMPLETE:
    602         rv = DoCreateStreamComplete(rv);
    603         break;
    604       default:
    605         NOTREACHED() << "bad state";
    606         rv = ERR_FAILED;
    607         break;
    608     }
    609   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
    610   return rv;
    611 }
    612 
    613 int HttpStreamFactoryImpl::Job::StartInternal() {
    614   CHECK_EQ(STATE_NONE, next_state_);
    615   next_state_ = STATE_START;
    616   int rv = RunLoop(OK);
    617   DCHECK_EQ(ERR_IO_PENDING, rv);
    618   return rv;
    619 }
    620 
    621 int HttpStreamFactoryImpl::Job::DoStart() {
    622   int port = request_info_.url.EffectiveIntPort();
    623   origin_ = HostPortPair(request_info_.url.HostNoBrackets(), port);
    624   origin_url_ = stream_factory_->ApplyHostMappingRules(
    625       request_info_.url, &origin_);
    626   http_pipelining_key_.reset(new HttpPipelinedHost::Key(origin_));
    627 
    628   net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_JOB,
    629                       base::Bind(&NetLogHttpStreamJobCallback,
    630                                  &request_info_.url, &origin_url_,
    631                                  priority_));
    632 
    633   // Don't connect to restricted ports.
    634   bool is_port_allowed = IsPortAllowedByDefault(port);
    635   if (request_info_.url.SchemeIs("ftp")) {
    636     // Never share connection with other jobs for FTP requests.
    637     DCHECK(!waiting_job_);
    638 
    639     is_port_allowed = IsPortAllowedByFtp(port);
    640   }
    641   if (!is_port_allowed && !IsPortAllowedByOverride(port)) {
    642     if (waiting_job_) {
    643       waiting_job_->Resume(this);
    644       waiting_job_ = NULL;
    645     }
    646     return ERR_UNSAFE_PORT;
    647   }
    648 
    649   next_state_ = STATE_RESOLVE_PROXY;
    650   return OK;
    651 }
    652 
    653 int HttpStreamFactoryImpl::Job::DoResolveProxy() {
    654   DCHECK(!pac_request_);
    655 
    656   next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
    657 
    658   if (request_info_.load_flags & LOAD_BYPASS_PROXY) {
    659     proxy_info_.UseDirect();
    660     return OK;
    661   }
    662 
    663   return session_->proxy_service()->ResolveProxy(
    664       request_info_.url, &proxy_info_, io_callback_, &pac_request_, net_log_);
    665 }
    666 
    667 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
    668   pac_request_ = NULL;
    669 
    670   if (result == OK) {
    671     // Remove unsupported proxies from the list.
    672     proxy_info_.RemoveProxiesWithoutScheme(
    673         ProxyServer::SCHEME_DIRECT |
    674         ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS |
    675         ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5);
    676 
    677     if (proxy_info_.is_empty()) {
    678       // No proxies/direct to choose from. This happens when we don't support
    679       // any of the proxies in the returned list.
    680       result = ERR_NO_SUPPORTED_PROXIES;
    681     }
    682   }
    683 
    684   if (result != OK) {
    685     if (waiting_job_) {
    686       waiting_job_->Resume(this);
    687       waiting_job_ = NULL;
    688     }
    689     return result;
    690   }
    691 
    692   if (blocking_job_)
    693     next_state_ = STATE_WAIT_FOR_JOB;
    694   else
    695     next_state_ = STATE_INIT_CONNECTION;
    696   return OK;
    697 }
    698 
    699 bool HttpStreamFactoryImpl::Job::ShouldForceSpdySSL() const {
    700   bool rv = force_spdy_always_ && force_spdy_over_ssl_;
    701   return rv && !HttpStreamFactory::HasSpdyExclusion(origin_);
    702 }
    703 
    704 bool HttpStreamFactoryImpl::Job::ShouldForceSpdyWithoutSSL() const {
    705   bool rv = force_spdy_always_ && !force_spdy_over_ssl_;
    706   return rv && !HttpStreamFactory::HasSpdyExclusion(origin_);
    707 }
    708 
    709 bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const {
    710   return session_->params().enable_quic &&
    711     session_->params().origin_to_force_quic_on.Equals(origin_) &&
    712     proxy_info_.is_direct();
    713 }
    714 
    715 int HttpStreamFactoryImpl::Job::DoWaitForJob() {
    716   DCHECK(blocking_job_);
    717   next_state_ = STATE_WAIT_FOR_JOB_COMPLETE;
    718   return ERR_IO_PENDING;
    719 }
    720 
    721 int HttpStreamFactoryImpl::Job::DoWaitForJobComplete(int result) {
    722   DCHECK(!blocking_job_);
    723   DCHECK_EQ(OK, result);
    724   next_state_ = STATE_INIT_CONNECTION;
    725   return OK;
    726 }
    727 
    728 int HttpStreamFactoryImpl::Job::DoInitConnection() {
    729   DCHECK(!blocking_job_);
    730   DCHECK(!connection_->is_initialized());
    731   DCHECK(proxy_info_.proxy_server().is_valid());
    732   next_state_ = STATE_INIT_CONNECTION_COMPLETE;
    733 
    734   using_ssl_ = request_info_.url.SchemeIs("https") ||
    735       request_info_.url.SchemeIs("wss") || ShouldForceSpdySSL();
    736   using_spdy_ = false;
    737 
    738   if (ShouldForceQuic())
    739     using_quic_ = true;
    740 
    741   if (using_quic_) {
    742     DCHECK(session_->params().enable_quic);
    743     if (!proxy_info_.is_direct()) {
    744       NOTREACHED();
    745       // TODO(rch): support QUIC proxies.
    746       return ERR_NOT_IMPLEMENTED;
    747     }
    748     next_state_ = STATE_INIT_CONNECTION_COMPLETE;
    749     const ProxyServer& proxy_server = proxy_info_.proxy_server();
    750     int rv = quic_request_.Request(HostPortProxyPair(origin_, proxy_server),
    751                                    using_ssl_, session_->cert_verifier(),
    752                                    net_log_, io_callback_);
    753     if (rv != OK) {
    754       // OK, there's no available QUIC session. Let |waiting_job_| resume
    755       // if it's paused.
    756       if (waiting_job_) {
    757         waiting_job_->Resume(this);
    758         waiting_job_ = NULL;
    759       }
    760     }
    761     return rv;
    762   }
    763 
    764   // Check first if we have a spdy session for this group.  If so, then go
    765   // straight to using that.
    766   SpdySessionKey spdy_session_key = GetSpdySessionKey();
    767   base::WeakPtr<SpdySession> spdy_session =
    768       session_->spdy_session_pool()->FindAvailableSession(
    769           spdy_session_key, net_log_);
    770   if (spdy_session && CanUseExistingSpdySession()) {
    771     // If we're preconnecting, but we already have a SpdySession, we don't
    772     // actually need to preconnect any sockets, so we're done.
    773     if (IsPreconnecting())
    774       return OK;
    775     using_spdy_ = true;
    776     next_state_ = STATE_CREATE_STREAM;
    777     existing_spdy_session_ = spdy_session;
    778     return OK;
    779   } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) {
    780     // Update the spdy session key for the request that launched this job.
    781     request_->SetSpdySessionKey(spdy_session_key);
    782   } else if (IsRequestEligibleForPipelining()) {
    783     // TODO(simonjam): With pipelining, we might be better off using fewer
    784     // connections and thus should make fewer preconnections. Explore
    785     // preconnecting fewer than the requested num_connections.
    786     //
    787     // Separate note: A forced pipeline is always available if one exists for
    788     // this key. This is different than normal pipelines, which may be
    789     // unavailable or unusable. So, there is no need to worry about a race
    790     // between when a pipeline becomes available and when this job blocks.
    791     existing_available_pipeline_ = stream_factory_->http_pipelined_host_pool_.
    792         IsExistingPipelineAvailableForKey(*http_pipelining_key_.get());
    793     if (existing_available_pipeline_) {
    794       return OK;
    795     } else {
    796       bool was_new_key = request_->SetHttpPipeliningKey(
    797           *http_pipelining_key_.get());
    798       if (!was_new_key && session_->force_http_pipelining()) {
    799         return ERR_IO_PENDING;
    800       }
    801     }
    802   }
    803 
    804   // OK, there's no available SPDY session. Let |waiting_job_| resume if it's
    805   // paused.
    806 
    807   if (waiting_job_) {
    808     waiting_job_->Resume(this);
    809     waiting_job_ = NULL;
    810   }
    811 
    812   if (proxy_info_.is_http() || proxy_info_.is_https())
    813     establishing_tunnel_ = using_ssl_;
    814 
    815   bool want_spdy_over_npn = original_url_ != NULL;
    816 
    817   if (proxy_info_.is_https()) {
    818     InitSSLConfig(proxy_info_.proxy_server().host_port_pair(),
    819                   &proxy_ssl_config_,
    820                   true /* is a proxy server */);
    821     // Disable revocation checking for HTTPS proxies since the revocation
    822     // requests are probably going to need to go through the proxy too.
    823     proxy_ssl_config_.rev_checking_enabled = false;
    824   }
    825   if (using_ssl_) {
    826     InitSSLConfig(origin_, &server_ssl_config_,
    827                   false /* not a proxy server */);
    828   }
    829 
    830   if (IsPreconnecting()) {
    831     DCHECK(!stream_factory_->for_websockets_);
    832     return PreconnectSocketsForHttpRequest(
    833         origin_url_,
    834         request_info_.extra_headers,
    835         request_info_.load_flags,
    836         priority_,
    837         session_,
    838         proxy_info_,
    839         ShouldForceSpdySSL(),
    840         want_spdy_over_npn,
    841         server_ssl_config_,
    842         proxy_ssl_config_,
    843         request_info_.privacy_mode,
    844         net_log_,
    845         num_streams_);
    846   } else {
    847     // If we can't use a SPDY session, don't both checking for one after
    848     // the hostname is resolved.
    849     OnHostResolutionCallback resolution_callback = CanUseExistingSpdySession() ?
    850         base::Bind(&Job::OnHostResolution, session_->spdy_session_pool(),
    851                    GetSpdySessionKey()) :
    852         OnHostResolutionCallback();
    853     if (stream_factory_->for_websockets_) {
    854       return InitSocketHandleForWebSocketRequest(
    855           origin_url_, request_info_.extra_headers, request_info_.load_flags,
    856           priority_, session_, proxy_info_, ShouldForceSpdySSL(),
    857           want_spdy_over_npn, server_ssl_config_, proxy_ssl_config_,
    858           request_info_.privacy_mode, net_log_,
    859           connection_.get(), resolution_callback, io_callback_);
    860     }
    861     return InitSocketHandleForHttpRequest(
    862         origin_url_, request_info_.extra_headers, request_info_.load_flags,
    863         priority_, session_, proxy_info_, ShouldForceSpdySSL(),
    864         want_spdy_over_npn, server_ssl_config_, proxy_ssl_config_,
    865         request_info_.privacy_mode, net_log_,
    866         connection_.get(), resolution_callback, io_callback_);
    867   }
    868 }
    869 
    870 int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
    871   if (IsPreconnecting()) {
    872     if (using_quic_)
    873       return result;
    874     DCHECK_EQ(OK, result);
    875     return OK;
    876   }
    877 
    878   if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) {
    879     // We found a SPDY connection after resolving the host.  This is
    880     // probably an IP pooled connection.
    881     SpdySessionKey spdy_session_key = GetSpdySessionKey();
    882     existing_spdy_session_ =
    883         session_->spdy_session_pool()->FindAvailableSession(
    884             spdy_session_key, net_log_);
    885     if (existing_spdy_session_) {
    886       using_spdy_ = true;
    887       next_state_ = STATE_CREATE_STREAM;
    888     } else {
    889       // It is possible that the spdy session no longer exists.
    890       ReturnToStateInitConnection(true /* close connection */);
    891     }
    892     return OK;
    893   }
    894 
    895   // TODO(willchan): Make this a bit more exact. Maybe there are recoverable
    896   // errors, such as ignoring certificate errors for Alternate-Protocol.
    897   if (result < 0 && waiting_job_) {
    898     waiting_job_->Resume(this);
    899     waiting_job_ = NULL;
    900   }
    901 
    902   if (result < 0 && session_->force_http_pipelining()) {
    903     stream_factory_->AbortPipelinedRequestsWithKey(
    904         this, *http_pipelining_key_.get(), result, server_ssl_config_);
    905   }
    906 
    907   // |result| may be the result of any of the stacked pools. The following
    908   // logic is used when determining how to interpret an error.
    909   // If |result| < 0:
    910   //   and connection_->socket() != NULL, then the SSL handshake ran and it
    911   //     is a potentially recoverable error.
    912   //   and connection_->socket == NULL and connection_->is_ssl_error() is true,
    913   //     then the SSL handshake ran with an unrecoverable error.
    914   //   otherwise, the error came from one of the other pools.
    915   bool ssl_started = using_ssl_ && (result == OK || connection_->socket() ||
    916                                     connection_->is_ssl_error());
    917 
    918   if (ssl_started && (result == OK || IsCertificateError(result))) {
    919     if (using_quic_ && result == OK) {
    920       was_npn_negotiated_ = true;
    921       NextProto protocol_negotiated =
    922           SSLClientSocket::NextProtoFromString("quic/1+spdy/3");
    923       protocol_negotiated_ = protocol_negotiated;
    924     } else {
    925       SSLClientSocket* ssl_socket =
    926           static_cast<SSLClientSocket*>(connection_->socket());
    927       if (ssl_socket->WasNpnNegotiated()) {
    928         was_npn_negotiated_ = true;
    929         std::string proto;
    930         std::string server_protos;
    931         SSLClientSocket::NextProtoStatus status =
    932             ssl_socket->GetNextProto(&proto, &server_protos);
    933         NextProto protocol_negotiated =
    934             SSLClientSocket::NextProtoFromString(proto);
    935         protocol_negotiated_ = protocol_negotiated;
    936         net_log_.AddEvent(
    937             NetLog::TYPE_HTTP_STREAM_REQUEST_PROTO,
    938             base::Bind(&NetLogHttpStreamProtoCallback,
    939                        status, &proto, &server_protos));
    940         if (ssl_socket->was_spdy_negotiated())
    941           SwitchToSpdyMode();
    942       }
    943       if (ShouldForceSpdySSL())
    944         SwitchToSpdyMode();
    945     }
    946   } else if (proxy_info_.is_https() && connection_->socket() &&
    947         result == OK) {
    948     ProxyClientSocket* proxy_socket =
    949       static_cast<ProxyClientSocket*>(connection_->socket());
    950     if (proxy_socket->IsUsingSpdy()) {
    951       was_npn_negotiated_ = true;
    952       protocol_negotiated_ = proxy_socket->GetProtocolNegotiated();
    953       SwitchToSpdyMode();
    954     }
    955   }
    956 
    957   // We may be using spdy without SSL
    958   if (ShouldForceSpdyWithoutSSL())
    959     SwitchToSpdyMode();
    960 
    961   if (result == ERR_PROXY_AUTH_REQUESTED ||
    962       result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
    963     DCHECK(!ssl_started);
    964     // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an
    965     // SSL socket, but there was an error before that could happen.  This
    966     // puts the in progress HttpProxy socket into |connection_| in order to
    967     // complete the auth (or read the response body).  The tunnel restart code
    968     // is careful to remove it before returning control to the rest of this
    969     // class.
    970     connection_.reset(connection_->release_pending_http_proxy_connection());
    971     return result;
    972   }
    973 
    974   if (!ssl_started && result < 0 && original_url_.get()) {
    975     // Mark the alternate protocol as broken and fallback.
    976     session_->http_server_properties()->SetBrokenAlternateProtocol(
    977         HostPortPair::FromURL(*original_url_));
    978     return result;
    979   }
    980 
    981   if (using_quic_) {
    982     if (result < 0)
    983       return result;
    984     stream_ = quic_request_.ReleaseStream();
    985     next_state_ = STATE_NONE;
    986     return OK;
    987   }
    988 
    989   if (result < 0 && !ssl_started)
    990     return ReconsiderProxyAfterError(result);
    991   establishing_tunnel_ = false;
    992 
    993   if (connection_->socket()) {
    994     LogHttpConnectedMetrics(*connection_);
    995 
    996     // We officially have a new connection.  Record the type.
    997     if (!connection_->is_reused()) {
    998       ConnectionType type = using_spdy_ ? CONNECTION_SPDY : CONNECTION_HTTP;
    999       UpdateConnectionTypeHistograms(type);
   1000     }
   1001   }
   1002 
   1003   // Handle SSL errors below.
   1004   if (using_ssl_) {
   1005     DCHECK(ssl_started);
   1006     if (IsCertificateError(result)) {
   1007       if (using_spdy_ && original_url_.get() &&
   1008           original_url_->SchemeIs("http")) {
   1009         // We ignore certificate errors for http over spdy.
   1010         spdy_certificate_error_ = result;
   1011         result = OK;
   1012       } else {
   1013         result = HandleCertificateError(result);
   1014         if (result == OK && !connection_->socket()->IsConnectedAndIdle()) {
   1015           ReturnToStateInitConnection(true /* close connection */);
   1016           return result;
   1017         }
   1018       }
   1019     }
   1020     if (result < 0)
   1021       return result;
   1022   }
   1023 
   1024   next_state_ = STATE_CREATE_STREAM;
   1025   return OK;
   1026 }
   1027 
   1028 int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) {
   1029   // This state indicates that the stream request is in a partially
   1030   // completed state, and we've called back to the delegate for more
   1031   // information.
   1032 
   1033   // We're always waiting here for the delegate to call us back.
   1034   return ERR_IO_PENDING;
   1035 }
   1036 
   1037 int HttpStreamFactoryImpl::Job::DoCreateStream() {
   1038   DCHECK(connection_->socket() || existing_spdy_session_.get() ||
   1039          existing_available_pipeline_ || using_quic_);
   1040 
   1041   next_state_ = STATE_CREATE_STREAM_COMPLETE;
   1042 
   1043   // We only set the socket motivation if we're the first to use
   1044   // this socket.  Is there a race for two SPDY requests?  We really
   1045   // need to plumb this through to the connect level.
   1046   if (connection_->socket() && !connection_->is_reused())
   1047     SetSocketMotivation();
   1048 
   1049   if (!using_spdy_) {
   1050     // We may get ftp scheme when fetching ftp resources through proxy.
   1051     bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) &&
   1052                        (request_info_.url.SchemeIs("http") ||
   1053                         request_info_.url.SchemeIs("ftp"));
   1054     if (stream_factory_->http_pipelined_host_pool_.
   1055             IsExistingPipelineAvailableForKey(*http_pipelining_key_.get())) {
   1056       DCHECK(!stream_factory_->for_websockets_);
   1057       stream_.reset(stream_factory_->http_pipelined_host_pool_.
   1058                     CreateStreamOnExistingPipeline(
   1059                         *http_pipelining_key_.get()));
   1060       CHECK(stream_.get());
   1061     } else if (stream_factory_->for_websockets_) {
   1062       DCHECK(request_);
   1063       DCHECK(request_->websocket_stream_factory());
   1064       websocket_stream_.reset(
   1065           request_->websocket_stream_factory()->CreateBasicStream(
   1066               connection_.release(), using_proxy));
   1067     } else if (!using_proxy && IsRequestEligibleForPipelining()) {
   1068       // TODO(simonjam): Support proxies.
   1069       stream_.reset(
   1070           stream_factory_->http_pipelined_host_pool_.CreateStreamOnNewPipeline(
   1071               *http_pipelining_key_.get(),
   1072               connection_.release(),
   1073               server_ssl_config_,
   1074               proxy_info_,
   1075               net_log_,
   1076               was_npn_negotiated_,
   1077               protocol_negotiated_));
   1078       CHECK(stream_.get());
   1079     } else {
   1080       stream_.reset(new HttpBasicStream(connection_.release(), NULL,
   1081                                         using_proxy));
   1082     }
   1083     return OK;
   1084   }
   1085 
   1086   CHECK(!stream_.get());
   1087 
   1088   bool direct = true;
   1089   const ProxyServer& proxy_server = proxy_info_.proxy_server();
   1090   PrivacyMode privacy_mode = request_info_.privacy_mode;
   1091   SpdySessionKey spdy_session_key(origin_, proxy_server, privacy_mode);
   1092   if (IsHttpsProxyAndHttpUrl()) {
   1093     // If we don't have a direct SPDY session, and we're using an HTTPS
   1094     // proxy, then we might have a SPDY session to the proxy.
   1095     // We never use privacy mode for connection to proxy server.
   1096     spdy_session_key = SpdySessionKey(proxy_server.host_port_pair(),
   1097                                       ProxyServer::Direct(),
   1098                                       kPrivacyModeDisabled);
   1099     direct = false;
   1100   }
   1101 
   1102   base::WeakPtr<SpdySession> spdy_session;
   1103   if (existing_spdy_session_.get()) {
   1104     // We picked up an existing session, so we don't need our socket.
   1105     if (connection_->socket())
   1106       connection_->socket()->Disconnect();
   1107     connection_->Reset();
   1108     std::swap(spdy_session, existing_spdy_session_);
   1109   } else {
   1110     SpdySessionPool* spdy_pool = session_->spdy_session_pool();
   1111     spdy_session = spdy_pool->FindAvailableSession(spdy_session_key, net_log_);
   1112     if (!spdy_session) {
   1113       int error =
   1114           spdy_pool->CreateAvailableSessionFromSocket(spdy_session_key,
   1115                                                       connection_.Pass(),
   1116                                                       net_log_,
   1117                                                       spdy_certificate_error_,
   1118                                                       &new_spdy_session_,
   1119                                                       using_ssl_);
   1120       if (error != OK)
   1121         return error;
   1122       const HostPortPair& host_port_pair = spdy_session_key.host_port_pair();
   1123       base::WeakPtr<HttpServerProperties> http_server_properties =
   1124           session_->http_server_properties();
   1125       if (http_server_properties)
   1126         http_server_properties->SetSupportsSpdy(host_port_pair, true);
   1127       spdy_session_direct_ = direct;
   1128       return OK;
   1129     }
   1130   }
   1131 
   1132   if (!spdy_session)
   1133     return ERR_CONNECTION_CLOSED;
   1134 
   1135   // TODO(willchan): Delete this code, because eventually, the
   1136   // HttpStreamFactoryImpl will be creating all the SpdyHttpStreams, since it
   1137   // will know when SpdySessions become available.
   1138 
   1139   if (stream_factory_->for_websockets_) {
   1140     DCHECK(request_);
   1141     DCHECK(request_->websocket_stream_factory());
   1142     bool use_relative_url = direct || request_info_.url.SchemeIs("wss");
   1143     websocket_stream_.reset(
   1144         request_->websocket_stream_factory()->CreateSpdyStream(
   1145             spdy_session, use_relative_url));
   1146   } else {
   1147     bool use_relative_url = direct || request_info_.url.SchemeIs("https");
   1148     stream_.reset(new SpdyHttpStream(spdy_session, use_relative_url));
   1149   }
   1150   return OK;
   1151 }
   1152 
   1153 int HttpStreamFactoryImpl::Job::DoCreateStreamComplete(int result) {
   1154   if (result < 0)
   1155     return result;
   1156 
   1157   session_->proxy_service()->ReportSuccess(proxy_info_);
   1158   next_state_ = STATE_NONE;
   1159   return OK;
   1160 }
   1161 
   1162 int HttpStreamFactoryImpl::Job::DoRestartTunnelAuth() {
   1163   next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE;
   1164   ProxyClientSocket* proxy_socket =
   1165       static_cast<ProxyClientSocket*>(connection_->socket());
   1166   return proxy_socket->RestartWithAuth(io_callback_);
   1167 }
   1168 
   1169 int HttpStreamFactoryImpl::Job::DoRestartTunnelAuthComplete(int result) {
   1170   if (result == ERR_PROXY_AUTH_REQUESTED)
   1171     return result;
   1172 
   1173   if (result == OK) {
   1174     // Now that we've got the HttpProxyClientSocket connected.  We have
   1175     // to release it as an idle socket into the pool and start the connection
   1176     // process from the beginning.  Trying to pass it in with the
   1177     // SSLSocketParams might cause a deadlock since params are dispatched
   1178     // interchangeably.  This request won't necessarily get this http proxy
   1179     // socket, but there will be forward progress.
   1180     establishing_tunnel_ = false;
   1181     ReturnToStateInitConnection(false /* do not close connection */);
   1182     return OK;
   1183   }
   1184 
   1185   return ReconsiderProxyAfterError(result);
   1186 }
   1187 
   1188 void HttpStreamFactoryImpl::Job::ReturnToStateInitConnection(
   1189     bool close_connection) {
   1190   if (close_connection && connection_->socket())
   1191     connection_->socket()->Disconnect();
   1192   connection_->Reset();
   1193 
   1194   if (request_) {
   1195     request_->RemoveRequestFromSpdySessionRequestMap();
   1196     request_->RemoveRequestFromHttpPipeliningRequestMap();
   1197   }
   1198 
   1199   next_state_ = STATE_INIT_CONNECTION;
   1200 }
   1201 
   1202 void HttpStreamFactoryImpl::Job::SetSocketMotivation() {
   1203   if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED)
   1204     connection_->socket()->SetSubresourceSpeculation();
   1205   else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED)
   1206     connection_->socket()->SetOmniboxSpeculation();
   1207   // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED).
   1208 }
   1209 
   1210 bool HttpStreamFactoryImpl::Job::IsHttpsProxyAndHttpUrl() const {
   1211   if (!proxy_info_.is_https())
   1212     return false;
   1213   if (original_url_.get()) {
   1214     // We currently only support Alternate-Protocol where the original scheme
   1215     // is http.
   1216     DCHECK(original_url_->SchemeIs("http"));
   1217     return original_url_->SchemeIs("http");
   1218   }
   1219   return request_info_.url.SchemeIs("http");
   1220 }
   1221 
   1222 // Sets several fields of ssl_config for the given origin_server based on the
   1223 // proxy info and other factors.
   1224 void HttpStreamFactoryImpl::Job::InitSSLConfig(
   1225     const HostPortPair& origin_server,
   1226     SSLConfig* ssl_config,
   1227     bool is_proxy) const {
   1228   if (proxy_info_.is_https() && ssl_config->send_client_cert) {
   1229     // When connecting through an HTTPS proxy, disable TLS False Start so
   1230     // that client authentication errors can be distinguished between those
   1231     // originating from the proxy server (ERR_PROXY_CONNECTION_FAILED) and
   1232     // those originating from the endpoint (ERR_SSL_PROTOCOL_ERROR /
   1233     // ERR_BAD_SSL_CLIENT_AUTH_CERT).
   1234     // TODO(rch): This assumes that the HTTPS proxy will only request a
   1235     // client certificate during the initial handshake.
   1236     // http://crbug.com/59292
   1237     ssl_config->false_start_enabled = false;
   1238   }
   1239 
   1240   enum {
   1241     FALLBACK_NONE = 0,    // SSL version fallback did not occur.
   1242     FALLBACK_SSL3 = 1,    // Fell back to SSL 3.0.
   1243     FALLBACK_TLS1 = 2,    // Fell back to TLS 1.0.
   1244     FALLBACK_TLS1_1 = 3,  // Fell back to TLS 1.1.
   1245     FALLBACK_MAX
   1246   };
   1247 
   1248   int fallback = FALLBACK_NONE;
   1249   if (ssl_config->version_fallback) {
   1250     switch (ssl_config->version_max) {
   1251       case SSL_PROTOCOL_VERSION_SSL3:
   1252         fallback = FALLBACK_SSL3;
   1253         break;
   1254       case SSL_PROTOCOL_VERSION_TLS1:
   1255         fallback = FALLBACK_TLS1;
   1256         break;
   1257       case SSL_PROTOCOL_VERSION_TLS1_1:
   1258         fallback = FALLBACK_TLS1_1;
   1259         break;
   1260     }
   1261   }
   1262   UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLVersionFallback",
   1263                             fallback, FALLBACK_MAX);
   1264 
   1265   // We also wish to measure the amount of fallback connections for a host that
   1266   // we know implements TLS up to 1.2. Ideally there would be no fallback here
   1267   // but high numbers of SSLv3 would suggest that SSLv3 fallback is being
   1268   // caused by network middleware rather than buggy HTTPS servers.
   1269   const std::string& host = origin_server.host();
   1270   if (!is_proxy &&
   1271       host.size() >= 10 &&
   1272       host.compare(host.size() - 10, 10, "google.com") == 0 &&
   1273       (host.size() == 10 || host[host.size()-11] == '.')) {
   1274     UMA_HISTOGRAM_ENUMERATION("Net.GoogleConnectionUsedSSLVersionFallback",
   1275                               fallback, FALLBACK_MAX);
   1276   }
   1277 
   1278   if (request_info_.load_flags & LOAD_VERIFY_EV_CERT)
   1279     ssl_config->verify_ev_cert = true;
   1280 
   1281   // Disable Channel ID if privacy mode is enabled.
   1282   if (request_info_.privacy_mode == kPrivacyModeEnabled)
   1283     ssl_config->channel_id_enabled = false;
   1284 }
   1285 
   1286 
   1287 int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) {
   1288   DCHECK(!pac_request_);
   1289 
   1290   // A failure to resolve the hostname or any error related to establishing a
   1291   // TCP connection could be grounds for trying a new proxy configuration.
   1292   //
   1293   // Why do this when a hostname cannot be resolved?  Some URLs only make sense
   1294   // to proxy servers.  The hostname in those URLs might fail to resolve if we
   1295   // are still using a non-proxy config.  We need to check if a proxy config
   1296   // now exists that corresponds to a proxy server that could load the URL.
   1297   //
   1298   switch (error) {
   1299     case ERR_PROXY_CONNECTION_FAILED:
   1300     case ERR_NAME_NOT_RESOLVED:
   1301     case ERR_INTERNET_DISCONNECTED:
   1302     case ERR_ADDRESS_UNREACHABLE:
   1303     case ERR_CONNECTION_CLOSED:
   1304     case ERR_CONNECTION_TIMED_OUT:
   1305     case ERR_CONNECTION_RESET:
   1306     case ERR_CONNECTION_REFUSED:
   1307     case ERR_CONNECTION_ABORTED:
   1308     case ERR_TIMED_OUT:
   1309     case ERR_TUNNEL_CONNECTION_FAILED:
   1310     case ERR_SOCKS_CONNECTION_FAILED:
   1311     // This can happen in the case of trying to talk to a proxy using SSL, and
   1312     // ending up talking to a captive portal that supports SSL instead.
   1313     case ERR_PROXY_CERTIFICATE_INVALID:
   1314     // This can happen when trying to talk SSL to a non-SSL server (Like a
   1315     // captive portal).
   1316     case ERR_SSL_PROTOCOL_ERROR:
   1317       break;
   1318     case ERR_SOCKS_CONNECTION_HOST_UNREACHABLE:
   1319       // Remap the SOCKS-specific "host unreachable" error to a more
   1320       // generic error code (this way consumers like the link doctor
   1321       // know to substitute their error page).
   1322       //
   1323       // Note that if the host resolving was done by the SOCKS5 proxy, we can't
   1324       // differentiate between a proxy-side "host not found" versus a proxy-side
   1325       // "address unreachable" error, and will report both of these failures as
   1326       // ERR_ADDRESS_UNREACHABLE.
   1327       return ERR_ADDRESS_UNREACHABLE;
   1328     default:
   1329       return error;
   1330   }
   1331 
   1332   if (request_info_.load_flags & LOAD_BYPASS_PROXY) {
   1333     return error;
   1334   }
   1335 
   1336   if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) {
   1337     session_->ssl_client_auth_cache()->Remove(
   1338         proxy_info_.proxy_server().host_port_pair().ToString());
   1339   }
   1340 
   1341   int rv = session_->proxy_service()->ReconsiderProxyAfterError(
   1342       request_info_.url, &proxy_info_, io_callback_, &pac_request_, net_log_);
   1343   if (rv == OK || rv == ERR_IO_PENDING) {
   1344     // If the error was during connection setup, there is no socket to
   1345     // disconnect.
   1346     if (connection_->socket())
   1347       connection_->socket()->Disconnect();
   1348     connection_->Reset();
   1349     if (request_) {
   1350       request_->RemoveRequestFromSpdySessionRequestMap();
   1351       request_->RemoveRequestFromHttpPipeliningRequestMap();
   1352     }
   1353     next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
   1354   } else {
   1355     // If ReconsiderProxyAfterError() failed synchronously, it means
   1356     // there was nothing left to fall-back to, so fail the transaction
   1357     // with the last connection error we got.
   1358     // TODO(eroman): This is a confusing contract, make it more obvious.
   1359     rv = error;
   1360   }
   1361 
   1362   return rv;
   1363 }
   1364 
   1365 int HttpStreamFactoryImpl::Job::HandleCertificateError(int error) {
   1366   DCHECK(using_ssl_);
   1367   DCHECK(IsCertificateError(error));
   1368 
   1369   SSLClientSocket* ssl_socket =
   1370       static_cast<SSLClientSocket*>(connection_->socket());
   1371   ssl_socket->GetSSLInfo(&ssl_info_);
   1372 
   1373   // Add the bad certificate to the set of allowed certificates in the
   1374   // SSL config object. This data structure will be consulted after calling
   1375   // RestartIgnoringLastError(). And the user will be asked interactively
   1376   // before RestartIgnoringLastError() is ever called.
   1377   SSLConfig::CertAndStatus bad_cert;
   1378 
   1379   // |ssl_info_.cert| may be NULL if we failed to create
   1380   // X509Certificate for whatever reason, but normally it shouldn't
   1381   // happen, unless this code is used inside sandbox.
   1382   if (ssl_info_.cert.get() == NULL ||
   1383       !X509Certificate::GetDEREncoded(ssl_info_.cert->os_cert_handle(),
   1384                                       &bad_cert.der_cert)) {
   1385     return error;
   1386   }
   1387   bad_cert.cert_status = ssl_info_.cert_status;
   1388   server_ssl_config_.allowed_bad_certs.push_back(bad_cert);
   1389 
   1390   int load_flags = request_info_.load_flags;
   1391   if (session_->params().ignore_certificate_errors)
   1392     load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS;
   1393   if (ssl_socket->IgnoreCertError(error, load_flags))
   1394     return OK;
   1395   return error;
   1396 }
   1397 
   1398 void HttpStreamFactoryImpl::Job::SwitchToSpdyMode() {
   1399   if (HttpStreamFactory::spdy_enabled())
   1400     using_spdy_ = true;
   1401 }
   1402 
   1403 // static
   1404 void HttpStreamFactoryImpl::Job::LogHttpConnectedMetrics(
   1405     const ClientSocketHandle& handle) {
   1406   UMA_HISTOGRAM_ENUMERATION("Net.HttpSocketType", handle.reuse_type(),
   1407                             ClientSocketHandle::NUM_TYPES);
   1408 
   1409   switch (handle.reuse_type()) {
   1410     case ClientSocketHandle::UNUSED:
   1411       UMA_HISTOGRAM_CUSTOM_TIMES("Net.HttpConnectionLatency",
   1412                                  handle.setup_time(),
   1413                                  base::TimeDelta::FromMilliseconds(1),
   1414                                  base::TimeDelta::FromMinutes(10),
   1415                                  100);
   1416       break;
   1417     case ClientSocketHandle::UNUSED_IDLE:
   1418       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SocketIdleTimeBeforeNextUse_UnusedSocket",
   1419                                  handle.idle_time(),
   1420                                  base::TimeDelta::FromMilliseconds(1),
   1421                                  base::TimeDelta::FromMinutes(6),
   1422                                  100);
   1423       break;
   1424     case ClientSocketHandle::REUSED_IDLE:
   1425       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SocketIdleTimeBeforeNextUse_ReusedSocket",
   1426                                  handle.idle_time(),
   1427                                  base::TimeDelta::FromMilliseconds(1),
   1428                                  base::TimeDelta::FromMinutes(6),
   1429                                  100);
   1430       break;
   1431     default:
   1432       NOTREACHED();
   1433       break;
   1434   }
   1435 }
   1436 
   1437 bool HttpStreamFactoryImpl::Job::IsPreconnecting() const {
   1438   DCHECK_GE(num_streams_, 0);
   1439   return num_streams_ > 0;
   1440 }
   1441 
   1442 bool HttpStreamFactoryImpl::Job::IsOrphaned() const {
   1443   return !IsPreconnecting() && !request_;
   1444 }
   1445 
   1446 bool HttpStreamFactoryImpl::Job::IsRequestEligibleForPipelining() {
   1447   if (IsPreconnecting() || !request_) {
   1448     return false;
   1449   }
   1450   if (stream_factory_->for_websockets_) {
   1451     return false;
   1452   }
   1453   if (session_->force_http_pipelining()) {
   1454     return true;
   1455   }
   1456   if (!session_->params().http_pipelining_enabled) {
   1457     return false;
   1458   }
   1459   if (using_ssl_) {
   1460     return false;
   1461   }
   1462   if (request_info_.method != "GET" && request_info_.method != "HEAD") {
   1463     return false;
   1464   }
   1465   if (request_info_.load_flags &
   1466       (net::LOAD_MAIN_FRAME | net::LOAD_SUB_FRAME | net::LOAD_PREFETCH |
   1467        net::LOAD_IS_DOWNLOAD)) {
   1468     // Avoid pipelining resources that may be streamed for a long time.
   1469     return false;
   1470   }
   1471   return stream_factory_->http_pipelined_host_pool_.IsKeyEligibleForPipelining(
   1472       *http_pipelining_key_.get());
   1473 }
   1474 
   1475 }  // namespace net
   1476