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