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