summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/http/http_stream_factory_impl.cc241
-rw-r--r--net/http/http_stream_factory_impl.h50
-rw-r--r--net/http/http_stream_factory_impl_job.cc136
-rw-r--r--net/http/http_stream_factory_impl_job.h25
-rw-r--r--net/http/http_stream_factory_impl_request.cc157
-rw-r--r--net/http/http_stream_factory_impl_request.h94
-rw-r--r--net/net.gyp2
-rw-r--r--net/proxy/proxy_server.h4
-rw-r--r--net/spdy/spdy_session_pool.h3
9 files changed, 412 insertions, 300 deletions
diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc
index 02dd29d..e4e94b1 100644
--- a/net/http/http_stream_factory_impl.cc
+++ b/net/http/http_stream_factory_impl.cc
@@ -5,191 +5,22 @@
#include "net/http/http_stream_factory_impl.h"
#include "base/stl_util-inl.h"
+#include "googleurl/src/gurl.h"
#include "net/base/net_log.h"
#include "net/base/net_util.h"
#include "net/http/http_network_session.h"
#include "net/http/http_stream_factory_impl_job.h"
+#include "net/http/http_stream_factory_impl_request.h"
+#include "net/spdy/spdy_http_stream.h"
namespace net {
-class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
- public:
- Request(HttpStreamFactoryImpl* factory,
- HttpStreamRequest::Delegate* delegate);
- virtual ~Request();
-
- Job* job() const { return job_; }
-
- // Binds |job| to this request.
- void BindJob(HttpStreamFactoryImpl::Job* job);
-
- // Marks completion of the request. Must be called before OnStreamReady().
- void Complete(bool was_alternate_protocol_available,
- bool was_npn_negotiated,
- bool using_spdy);
-
- // HttpStreamRequest::Delegate methods which we implement. Note we don't
- // actually subclass HttpStreamRequest::Delegate.
-
- void OnStreamReady(
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- HttpStream* stream);
- void OnStreamFailed(int status, const SSLConfig& used_ssl_config);
- void OnCertificateError(int status,
- const SSLConfig& used_ssl_config,
- const SSLInfo& ssl_info);
- void OnNeedsProxyAuth(const HttpResponseInfo& proxy_response,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- HttpAuthController* auth_controller);
- void OnNeedsClientAuth(const SSLConfig& used_ssl_config,
- SSLCertRequestInfo* cert_info);
- void OnHttpsProxyTunnelResponse(
- const HttpResponseInfo& response_info,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- HttpStream* stream);
-
- // HttpStreamRequest methods.
-
- virtual int RestartTunnelWithProxyAuth(const string16& username,
- const string16& password);
- virtual LoadState GetLoadState() const;
- virtual bool was_alternate_protocol_available() const;
- virtual bool was_npn_negotiated() const;
- virtual bool using_spdy() const;
-
- private:
- HttpStreamFactoryImpl* const factory_;
- HttpStreamRequest::Delegate* const delegate_;
-
- // The |job_| that this request is tied to.
- // TODO(willchan): Revisit this when we decouple requests and jobs further.
- HttpStreamFactoryImpl::Job* job_;
-
- bool completed_;
- bool was_alternate_protocol_available_;
- bool was_npn_negotiated_;
- bool using_spdy_;
- DISALLOW_COPY_AND_ASSIGN(Request);
-};
-
-HttpStreamFactoryImpl::Request::Request(HttpStreamFactoryImpl* factory,
- HttpStreamRequest::Delegate* delegate)
- : factory_(factory),
- delegate_(delegate),
- job_(NULL),
- completed_(false),
- was_alternate_protocol_available_(false),
- was_npn_negotiated_(false),
- using_spdy_(false) {
- DCHECK(factory_);
- DCHECK(delegate_);
-}
-
-HttpStreamFactoryImpl::Request::~Request() {
- factory_->request_map_.erase(job_);
-
- // TODO(willchan): Remove this when we decouple requests and jobs.
- delete job_;
-}
-
-void HttpStreamFactoryImpl::Request::BindJob(HttpStreamFactoryImpl::Job* job) {
- DCHECK(job);
- DCHECK(!job_);
- job_ = job;
-}
-
-void HttpStreamFactoryImpl::Request::Complete(
- bool was_alternate_protocol_available,
- bool was_npn_negotiated,
- bool using_spdy) {
- DCHECK(!completed_);
- completed_ = true;
- was_alternate_protocol_available_ = was_alternate_protocol_available;
- was_npn_negotiated_ = was_npn_negotiated;
- using_spdy_ = using_spdy;
-}
-
-void HttpStreamFactoryImpl::Request::OnStreamReady(
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- HttpStream* stream) {
- DCHECK(stream);
- DCHECK(completed_);
- delegate_->OnStreamReady(used_ssl_config, used_proxy_info, stream);
-}
-
-void HttpStreamFactoryImpl::Request::OnStreamFailed(
- int status,
- const SSLConfig& used_ssl_config) {
- DCHECK_NE(OK, status);
- delegate_->OnStreamFailed(status, used_ssl_config);
-}
-
-void HttpStreamFactoryImpl::Request::OnCertificateError(
- int status,
- const SSLConfig& used_ssl_config,
- const SSLInfo& ssl_info) {
- DCHECK_NE(OK, status);
- delegate_->OnCertificateError(status, used_ssl_config, ssl_info);
-}
-
-void HttpStreamFactoryImpl::Request::OnNeedsProxyAuth(
- const HttpResponseInfo& proxy_response,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- HttpAuthController* auth_controller) {
- delegate_->OnNeedsProxyAuth(
- proxy_response, used_ssl_config, used_proxy_info, auth_controller);
-}
-
-void HttpStreamFactoryImpl::Request::OnNeedsClientAuth(
- const SSLConfig& used_ssl_config,
- SSLCertRequestInfo* cert_info) {
- delegate_->OnNeedsClientAuth(used_ssl_config, cert_info);
-}
-
-void HttpStreamFactoryImpl::Request::OnHttpsProxyTunnelResponse(
- const HttpResponseInfo& response_info,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- HttpStream* stream) {
- delegate_->OnHttpsProxyTunnelResponse(
- response_info, used_ssl_config, used_proxy_info, stream);
-}
-
-int HttpStreamFactoryImpl::Request::RestartTunnelWithProxyAuth(
- const string16& username,
- const string16& password) {
- return job_->RestartTunnelWithProxyAuth(username, password);
-}
-
-LoadState HttpStreamFactoryImpl::Request::GetLoadState() const {
- return factory_->GetLoadState(*this);
-}
-
-bool HttpStreamFactoryImpl::Request::was_alternate_protocol_available() const {
- DCHECK(completed_);
- return was_alternate_protocol_available_;
-}
-
-bool HttpStreamFactoryImpl::Request::was_npn_negotiated() const {
- DCHECK(completed_);
- return was_npn_negotiated_;
-}
-
-bool HttpStreamFactoryImpl::Request::using_spdy() const {
- DCHECK(completed_);
- return using_spdy_;
-}
-
HttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session)
: session_(session) {}
HttpStreamFactoryImpl::~HttpStreamFactoryImpl() {
DCHECK(request_map_.empty());
+ DCHECK(spdy_session_request_map_.empty());
std::set<const Job*> tmp_job_set;
tmp_job_set.swap(preconnect_job_set_);
@@ -203,10 +34,10 @@ HttpStreamRequest* HttpStreamFactoryImpl::RequestStream(
HttpStreamRequest::Delegate* delegate,
const BoundNetLog& net_log) {
Job* job = new Job(this, session_);
- Request* request = new Request(this, delegate);
+ Request* request = new Request(request_info.url, this, delegate);
request_map_[job] = request;
request->BindJob(job);
- job->Start(request_info, ssl_config, net_log);
+ job->Start(request, request_info, ssl_config, net_log);
return request;
}
@@ -233,61 +64,21 @@ LoadState HttpStreamFactoryImpl::GetLoadState(const Request& request) const {
return request.job()->GetLoadState();
}
-void HttpStreamFactoryImpl::OnStreamReady(const Job* job,
- const SSLConfig& ssl_config,
- const ProxyInfo& proxy_info,
- HttpStream* stream) {
+void HttpStreamFactoryImpl::OnSpdySessionReady(
+ const Job* job,
+ scoped_refptr<SpdySession> spdy_session,
+ bool direct) {
+ DCHECK(job->using_spdy());
DCHECK(ContainsKey(request_map_, job));
Request* request = request_map_[job];
request->Complete(job->was_alternate_protocol_available(),
job->was_npn_negotiated(),
job->using_spdy());
- request->OnStreamReady(ssl_config, proxy_info, stream);
-}
-
-void HttpStreamFactoryImpl::OnStreamFailed(const Job* job,
- int result,
- const SSLConfig& ssl_config) {
- DCHECK(ContainsKey(request_map_, job));
- request_map_[job]->OnStreamFailed(result, ssl_config);
-}
-
-void HttpStreamFactoryImpl::OnCertificateError(const Job* job,
- int result,
- const SSLConfig& ssl_config,
- const SSLInfo& ssl_info) {
- DCHECK(ContainsKey(request_map_, job));
- request_map_[job]->OnCertificateError(result, ssl_config, ssl_info);
-}
-
-void HttpStreamFactoryImpl::OnNeedsProxyAuth(
- const Job* job,
- const HttpResponseInfo& response,
- const SSLConfig& ssl_config,
- const ProxyInfo& proxy_info,
- HttpAuthController* auth_controller) {
- DCHECK(ContainsKey(request_map_, job));
- request_map_[job]->OnNeedsProxyAuth(
- response, ssl_config, proxy_info, auth_controller);
-}
-
-void HttpStreamFactoryImpl::OnNeedsClientAuth(
- const Job* job,
- const SSLConfig& ssl_config,
- SSLCertRequestInfo* cert_info) {
- DCHECK(ContainsKey(request_map_, job));
- request_map_[job]->OnNeedsClientAuth(ssl_config, cert_info);
-}
-
-void HttpStreamFactoryImpl::OnHttpsProxyTunnelResponse(
- const Job* job,
- const HttpResponseInfo& response_info,
- const SSLConfig& ssl_config,
- const ProxyInfo& proxy_info,
- HttpStream* stream) {
- DCHECK(ContainsKey(request_map_, job));
- request_map_[job]->OnHttpsProxyTunnelResponse(
- response_info, ssl_config, proxy_info, stream);
+ bool use_relative_url = direct || request->url().SchemeIs("https");
+ request->OnStreamReady(
+ job->ssl_config(),
+ job->proxy_info(),
+ new SpdyHttpStream(spdy_session, use_relative_url));
}
void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) {
diff --git a/net/http/http_stream_factory_impl.h b/net/http/http_stream_factory_impl.h
index d86a8fa..9d6e133 100644
--- a/net/http/http_stream_factory_impl.h
+++ b/net/http/http_stream_factory_impl.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -9,11 +9,14 @@
#include <set>
#include <string>
+#include "base/ref_counted.h"
#include "net/http/http_stream_factory.h"
+#include "net/proxy/proxy_server.h"
namespace net {
class HttpNetworkSession;
+class SpdySession;
class HttpStreamFactoryImpl : public HttpStreamFactory {
public:
@@ -38,31 +41,24 @@ class HttpStreamFactoryImpl : public HttpStreamFactory {
class Request;
class Job;
+ typedef std::set<Request*> RequestSet;
+ typedef std::map<HostPortProxyPair, RequestSet> SpdySessionRequestMap;
+
LoadState GetLoadState(const Request& request) const;
- void OnStreamReady(const Job* job,
- const SSLConfig& ssl_config,
- const ProxyInfo& proxy_info,
- HttpStream* stream);
- void OnStreamFailed(const Job* job, int result, const SSLConfig& ssl_config);
- void OnCertificateError(const Job* job,
- int result,
- const SSLConfig& ssl_config,
- const SSLInfo& ssl_info);
- void OnNeedsProxyAuth(const Job* job,
- const HttpResponseInfo& response_info,
- const SSLConfig& ssl_config,
- const ProxyInfo& proxy_info,
- HttpAuthController* auth_controller);
- void OnNeedsClientAuth(const Job* job,
- const SSLConfig& ssl_config,
- SSLCertRequestInfo* cert_info);
- void OnHttpsProxyTunnelResponse(const Job* job,
- const HttpResponseInfo& response_info,
- const SSLConfig& ssl_config,
- const ProxyInfo& proxy_info,
- HttpStream* stream);
+ // Called when a SpdySession is ready. It will find appropriate Requests and
+ // fulfill them. |direct| indicates whether or not |spdy_session| uses a
+ // proxy.
+ void OnSpdySessionReady(const Job* job,
+ scoped_refptr<SpdySession> spdy_session,
+ bool direct);
+
+ // Called when the Job detects that the endpoint indicated by the
+ // Alternate-Protocol does not work. Lets the factory update
+ // HttpAlternateProtocols with the failure and resets the SPDY session key.
+ void OnBrokenAlternateProtocol(const Job*, const HostPortPair& origin);
+ // Invoked when the Job finishes preconnecting sockets.
void OnPreconnectsComplete(const Job* job);
// Called when the Preconnect completes. Used for testing.
@@ -74,13 +70,11 @@ class HttpStreamFactoryImpl : public HttpStreamFactory {
// All Requests are handed out to clients. By the time HttpStreamFactoryImpl
// is destroyed, all Requests should be deleted (which should remove them from
- // |request_map_|.
- // TODO(willchan): Change to a different key when we enable late binding. This
- // is the key part that keeps things tightly bound.
- // Note that currently the Request assumes ownership of the Job. We will break
- // this with late binding, and the factory will own the Job.
+ // |request_map_|. The Requests will delete the corresponding job.
std::map<const Job*, Request*> request_map_;
+ SpdySessionRequestMap spdy_session_request_map_;
+
// These jobs correspond to preconnect requests and have no associated Request
// object. They're owned by HttpStreamFactoryImpl. Leftover jobs will be
// deleted when the factory is destroyed.
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index 3f1968c..6884a79 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -18,6 +18,7 @@
#include "net/http/http_proxy_client_socket.h"
#include "net/http/http_proxy_client_socket_pool.h"
#include "net/http/http_request_info.h"
+#include "net/http/http_stream_factory_impl_request.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool.h"
#include "net/socket/socks_client_socket_pool.h"
@@ -47,7 +48,8 @@ GURL UpgradeUrlToHttps(const GURL& original_url) {
HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory,
HttpNetworkSession* session)
- : ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(this, &Job::OnIOComplete)),
+ : request_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(this, &Job::OnIOComplete)),
connection_(new ClientSocketHandle),
session_(session),
stream_factory_(stream_factory),
@@ -63,7 +65,10 @@ HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory,
was_alternate_protocol_available_(false),
was_npn_negotiated_(false),
num_streams_(0),
+ spdy_session_direct_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+ DCHECK(stream_factory);
+ DCHECK(session);
if (HttpStreamFactory::use_alternate_protocols())
alternate_protocol_mode_ = kUnspecified;
else
@@ -87,9 +92,12 @@ HttpStreamFactoryImpl::Job::~Job() {
stream_->Close(true /* not reusable */);
}
-void HttpStreamFactoryImpl::Job::Start(const HttpRequestInfo& request_info,
+void HttpStreamFactoryImpl::Job::Start(Request* request,
+ const HttpRequestInfo& request_info,
const SSLConfig& ssl_config,
const BoundNetLog& net_log) {
+ DCHECK(request);
+ request_ = request;
StartInternal(request_info, ssl_config, net_log);
}
@@ -135,6 +143,14 @@ bool HttpStreamFactoryImpl::Job::using_spdy() const {
return using_spdy_;
}
+const SSLConfig& HttpStreamFactoryImpl::Job::ssl_config() const {
+ return ssl_config_;
+}
+
+const ProxyInfo& HttpStreamFactoryImpl::Job::proxy_info() const {
+ return proxy_info_;
+}
+
void HttpStreamFactoryImpl::Job::GetSSLInfo() {
DCHECK(using_ssl_);
DCHECK(!establishing_tunnel_);
@@ -146,40 +162,59 @@ void HttpStreamFactoryImpl::Job::GetSSLInfo() {
void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() {
DCHECK(stream_.get());
- stream_factory_->OnStreamReady(
- this, ssl_config_, proxy_info_, stream_.release());
+ request_->Complete(was_alternate_protocol_available(),
+ was_npn_negotiated(),
+ using_spdy());
+ request_->OnStreamReady(ssl_config_, proxy_info_, stream_.release());
+ // |this| may be deleted after this call.
+}
+
+void HttpStreamFactoryImpl::Job::OnSpdySessionReadyCallback() {
+ DCHECK(!stream_.get());
+ DCHECK(using_spdy());
+ DCHECK(new_spdy_session_);
+ scoped_refptr<SpdySession> spdy_session = new_spdy_session_;
+ new_spdy_session_ = NULL;
+ stream_factory_->OnSpdySessionReady(this, spdy_session, spdy_session_direct_);
+ // |this| may be deleted after this call.
}
void HttpStreamFactoryImpl::Job::OnStreamFailedCallback(int result) {
- stream_factory_->OnStreamFailed(this, result, ssl_config_);
+ request_->OnStreamFailed(result, ssl_config_);
+ // |this| may be deleted after this call.
}
void HttpStreamFactoryImpl::Job::OnCertificateErrorCallback(
int result, const SSLInfo& ssl_info) {
- stream_factory_->OnCertificateError(this, result, ssl_config_, ssl_info);
+ request_->OnCertificateError(result, ssl_config_, ssl_info);
+ // |this| may be deleted after this call.
}
void HttpStreamFactoryImpl::Job::OnNeedsProxyAuthCallback(
const HttpResponseInfo& response,
HttpAuthController* auth_controller) {
- stream_factory_->OnNeedsProxyAuth(
- this, response, ssl_config_, proxy_info_, auth_controller);
+ request_->OnNeedsProxyAuth(
+ response, ssl_config_, proxy_info_, auth_controller);
+ // |this| may be deleted after this call.
}
void HttpStreamFactoryImpl::Job::OnNeedsClientAuthCallback(
SSLCertRequestInfo* cert_info) {
- stream_factory_->OnNeedsClientAuth(this, ssl_config_, cert_info);
+ request_->OnNeedsClientAuth(ssl_config_, cert_info);
+ // |this| may be deleted after this call.
}
void HttpStreamFactoryImpl::Job::OnHttpsProxyTunnelResponseCallback(
const HttpResponseInfo& response_info,
HttpStream* stream) {
- stream_factory_->OnHttpsProxyTunnelResponse(
- this, response_info, ssl_config_, proxy_info_, stream);
+ request_->OnHttpsProxyTunnelResponse(
+ response_info, ssl_config_, proxy_info_, stream);
+ // |this| may be deleted after this call.
}
void HttpStreamFactoryImpl::Job::OnPreconnectsComplete() {
stream_factory_->OnPreconnectsComplete(this);
+ // |this| may be deleted after this call.
}
void HttpStreamFactoryImpl::Job::OnIOComplete(int result) {
@@ -262,10 +297,17 @@ int HttpStreamFactoryImpl::Job::RunLoop(int result) {
case OK:
next_state_ = STATE_DONE;
- MessageLoop::current()->PostTask(
- FROM_HERE,
- method_factory_.NewRunnableMethod(
- &HttpStreamFactoryImpl::Job::OnStreamReadyCallback));
+ if (new_spdy_session_) {
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &HttpStreamFactoryImpl::Job::OnSpdySessionReadyCallback));
+ } else {
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &HttpStreamFactoryImpl::Job::OnStreamReadyCallback));
+ }
return ERR_IO_PENDING;
default:
@@ -455,8 +497,16 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() {
if (HttpStreamFactory::spdy_enabled() && !HasSpdyExclusion(endpoint_)) {
// Check first if we have a spdy session for this group. If so, then go
// straight to using that.
- HostPortProxyPair pair(endpoint_, proxy_info_.proxy_server());
- if (session_->spdy_session_pool()->HasSession(pair)) {
+ HostPortProxyPair spdy_session_key;
+ if (IsHttpsProxyAndHttpUrl()) {
+ spdy_session_key =
+ HostPortProxyPair(proxy_info_.proxy_server().host_port_pair(),
+ ProxyServer::Direct());
+ } else {
+ spdy_session_key =
+ HostPortProxyPair(endpoint_, proxy_info_.proxy_server());
+ }
+ if (session_->spdy_session_pool()->HasSession(spdy_session_key)) {
// If we're preconnecting, but we already have a SpdySession, we don't
// actually need to preconnect any sockets, so we're done.
if (IsPreconnecting())
@@ -464,17 +514,9 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() {
using_spdy_ = true;
next_state_ = STATE_CREATE_STREAM;
return OK;
- }
- // Check next if we have a spdy session for this proxy. If so, then go
- // straight to using that.
- if (IsHttpsProxyAndHttpUrl()) {
- HostPortProxyPair proxy(proxy_info_.proxy_server().host_port_pair(),
- ProxyServer::Direct());
- if (session_->spdy_session_pool()->HasSession(proxy)) {
- using_spdy_ = true;
- next_state_ = STATE_CREATE_STREAM;
- return OK;
- }
+ } else if (!IsPreconnecting()) {
+ // Update the spdy session key for the request that launched this job.
+ request_->SetSpdySessionKey(spdy_session_key);
}
}
@@ -719,9 +761,7 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
} else {
result = HandleCertificateError(result);
if (result == OK && !connection_->socket()->IsConnectedAndIdle()) {
- connection_->socket()->Disconnect();
- connection_->Reset();
- next_state_ = STATE_INIT_CONNECTION;
+ ReturnToStateInitConnection(true /* close connection */);
return result;
}
}
@@ -775,7 +815,7 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
spdy_session = spdy_pool->Get(pair, net_log_);
} else if (IsHttpsProxyAndHttpUrl()) {
// If we don't have a direct SPDY session, and we're using an HTTPS
- // proxy, then we might have a SPDY session to the proxy
+ // proxy, then we might have a SPDY session to the proxy.
pair = HostPortProxyPair(proxy_server.host_port_pair(),
ProxyServer::Direct());
if (spdy_pool->HasSession(pair)) {
@@ -799,11 +839,19 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
&spdy_session, using_ssl_);
if (error != OK)
return error;
+ new_spdy_session_ = spdy_session;
+ spdy_session_direct_ = direct;
+ return OK;
}
if (spdy_session->IsClosed())
return ERR_CONNECTION_CLOSED;
+ // TODO(willchan): Delete this code, because eventually, the
+ // HttpStreamFactoryImpl will be creating all the SpdyHttpStreams, since it
+ // will know when SpdySessions become available. The above HasSession() checks
+ // will be able to be deleted too.
+
bool use_relative_url = direct || request_info_.url.SchemeIs("https");
stream_.reset(new SpdyHttpStream(spdy_session, use_relative_url));
return OK;
@@ -835,15 +883,26 @@ int HttpStreamFactoryImpl::Job::DoRestartTunnelAuthComplete(int result) {
// SSLSocketParams might cause a deadlock since params are dispatched
// interchangeably. This request won't necessarily get this http proxy
// socket, but there will be forward progress.
- connection_->Reset();
establishing_tunnel_ = false;
- next_state_ = STATE_INIT_CONNECTION;
+ ReturnToStateInitConnection(false /* do not close connection */);
return OK;
}
return ReconsiderProxyAfterError(result);
}
+void HttpStreamFactoryImpl::Job::ReturnToStateInitConnection(
+ bool close_connection) {
+ if (close_connection && connection_->socket())
+ connection_->socket()->Disconnect();
+ connection_->Reset();
+
+ if (request_)
+ request_->RemoveRequestFromSpdySessionRequestMap();
+
+ next_state_ = STATE_INIT_CONNECTION;
+}
+
void HttpStreamFactoryImpl::Job::SetSocketMotivation() {
if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED)
connection_->socket()->SetSubresourceSpeculation();
@@ -925,10 +984,7 @@ void HttpStreamFactoryImpl::Job::MarkBrokenAlternateProtocolAndFallback() {
endpoint_);
alternate_protocol_mode_ = kDoNotUseAlternateProtocol;
- if (connection_->socket())
- connection_->socket()->Disconnect();
- connection_->Reset();
- next_state_ = STATE_INIT_CONNECTION;
+ ReturnToStateInitConnection(false /* close connection */);
}
int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) {
@@ -987,6 +1043,8 @@ int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) {
if (connection_->socket())
connection_->socket()->Disconnect();
connection_->Reset();
+ if (request_)
+ request_->RemoveRequestFromSpdySessionRequestMap();
next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
} else {
// If ReconsiderProxyAfterError() failed synchronously, it means
diff --git a/net/http/http_stream_factory_impl_job.h b/net/http/http_stream_factory_impl_job.h
index 38f8081..59b0b09 100644
--- a/net/http/http_stream_factory_impl_job.h
+++ b/net/http/http_stream_factory_impl_job.h
@@ -33,7 +33,8 @@ class TCPSocketParams;
// created for the StreamFactory.
class HttpStreamFactoryImpl::Job {
public:
- Job(HttpStreamFactoryImpl* stream_factory, HttpNetworkSession* session);
+ Job(HttpStreamFactoryImpl* stream_factory,
+ HttpNetworkSession* session);
~Job();
// Start initiates the process of creating a new HttpStream.
@@ -41,7 +42,8 @@ class HttpStreamFactoryImpl::Job {
// lifecycle of these parameters will remain valid until the stream is
// created, failed, or destroyed. In the first two cases, the delegate will
// be called to notify completion of the request.
- void Start(const HttpRequestInfo& request_info,
+ void Start(Request* request,
+ const HttpRequestInfo& request_info,
const SSLConfig& ssl_config,
const BoundNetLog& net_log);
@@ -58,6 +60,12 @@ class HttpStreamFactoryImpl::Job {
bool was_npn_negotiated() const;
bool using_spdy() const;
+ const SSLConfig& ssl_config() const;
+ const ProxyInfo& proxy_info() const;
+
+ // Indicates whether or not this job is performing a preconnect.
+ bool IsPreconnecting() const;
+
private:
enum AlternateProtocolMode {
kUnspecified, // Unspecified, check HttpAlternateProtocols
@@ -82,6 +90,7 @@ class HttpStreamFactoryImpl::Job {
};
void OnStreamReadyCallback();
+ void OnSpdySessionReadyCallback();
void OnStreamFailedCallback(int result);
void OnCertificateErrorCallback(int result, const SSLInfo& ssl_info);
void OnNeedsProxyAuthCallback(const HttpResponseInfo& response_info,
@@ -112,6 +121,9 @@ class HttpStreamFactoryImpl::Job {
int DoRestartTunnelAuth();
int DoRestartTunnelAuthComplete(int result);
+ // Returns to STATE_INIT_CONNECTION and resets some state.
+ void ReturnToStateInitConnection(bool close_connection);
+
// Set the motivation for this request onto the underlying socket.
void SetSocketMotivation();
@@ -163,8 +175,7 @@ class HttpStreamFactoryImpl::Job {
// Record histograms of latency until Connect() completes.
static void LogHttpConnectedMetrics(const ClientSocketHandle& handle);
- // Indicates whether or not this job is performing a preconnect.
- bool IsPreconnecting() const;
+ Request* request_;
HttpRequestInfo request_info_;
ProxyInfo proxy_info_;
@@ -222,6 +233,12 @@ class HttpStreamFactoryImpl::Job {
// preconnect.
int num_streams_;
+ // Initialized when we create a new SpdySession.
+ scoped_refptr<SpdySession> new_spdy_session_;
+
+ // Only used if |new_spdy_session_| is non-NULL.
+ bool spdy_session_direct_;
+
ScopedRunnableMethodFactory<Job> method_factory_;
DISALLOW_COPY_AND_ASSIGN(Job);
diff --git a/net/http/http_stream_factory_impl_request.cc b/net/http/http_stream_factory_impl_request.cc
new file mode 100644
index 0000000..7826659
--- /dev/null
+++ b/net/http/http_stream_factory_impl_request.cc
@@ -0,0 +1,157 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/http/http_stream_factory_impl_request.h"
+
+#include "base/logging.h"
+#include "base/stl_util-inl.h"
+#include "net/http/http_stream_factory_impl_job.h"
+
+namespace net {
+
+HttpStreamFactoryImpl::Request::Request(const GURL& url,
+ HttpStreamFactoryImpl* factory,
+ HttpStreamRequest::Delegate* delegate)
+ : url_(url),
+ factory_(factory),
+ delegate_(delegate),
+ job_(NULL),
+ completed_(false),
+ was_alternate_protocol_available_(false),
+ was_npn_negotiated_(false),
+ using_spdy_(false) {
+ DCHECK(factory_);
+ DCHECK(delegate_);
+}
+
+HttpStreamFactoryImpl::Request::~Request() {
+ factory_->request_map_.erase(job_);
+
+ // TODO(willchan): Remove this when we decouple requests and jobs.
+ delete job_;
+
+ RemoveRequestFromSpdySessionRequestMap();
+}
+
+void HttpStreamFactoryImpl::Request::SetSpdySessionKey(
+ const HostPortProxyPair& spdy_session_key) {
+ DCHECK(!spdy_session_key_.get());
+ spdy_session_key_.reset(new HostPortProxyPair(spdy_session_key));
+ RequestSet& request_set =
+ factory_->spdy_session_request_map_[spdy_session_key];
+ DCHECK(!ContainsKey(request_set, this));
+ request_set.insert(this);
+}
+
+void HttpStreamFactoryImpl::Request::BindJob(HttpStreamFactoryImpl::Job* job) {
+ DCHECK(job);
+ DCHECK(!job_);
+ job_ = job;
+}
+
+void HttpStreamFactoryImpl::Request::Complete(
+ bool was_alternate_protocol_available,
+ bool was_npn_negotiated,
+ bool using_spdy) {
+ DCHECK(!completed_);
+ completed_ = true;
+ was_alternate_protocol_available_ = was_alternate_protocol_available;
+ was_npn_negotiated_ = was_npn_negotiated;
+ using_spdy_ = using_spdy;
+}
+
+void HttpStreamFactoryImpl::Request::OnStreamReady(
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ HttpStream* stream) {
+ DCHECK(stream);
+ DCHECK(completed_);
+ delegate_->OnStreamReady(used_ssl_config, used_proxy_info, stream);
+}
+
+void HttpStreamFactoryImpl::Request::OnStreamFailed(
+ int status,
+ const SSLConfig& used_ssl_config) {
+ DCHECK_NE(OK, status);
+ delegate_->OnStreamFailed(status, used_ssl_config);
+}
+
+void HttpStreamFactoryImpl::Request::OnCertificateError(
+ int status,
+ const SSLConfig& used_ssl_config,
+ const SSLInfo& ssl_info) {
+ DCHECK_NE(OK, status);
+ delegate_->OnCertificateError(status, used_ssl_config, ssl_info);
+}
+
+void HttpStreamFactoryImpl::Request::OnNeedsProxyAuth(
+ const HttpResponseInfo& proxy_response,
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ HttpAuthController* auth_controller) {
+ delegate_->OnNeedsProxyAuth(
+ proxy_response, used_ssl_config, used_proxy_info, auth_controller);
+}
+
+void HttpStreamFactoryImpl::Request::OnNeedsClientAuth(
+ const SSLConfig& used_ssl_config,
+ SSLCertRequestInfo* cert_info) {
+ delegate_->OnNeedsClientAuth(used_ssl_config, cert_info);
+}
+
+void HttpStreamFactoryImpl::Request::OnHttpsProxyTunnelResponse(
+ const HttpResponseInfo& response_info,
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ HttpStream* stream) {
+ delegate_->OnHttpsProxyTunnelResponse(
+ response_info, used_ssl_config, used_proxy_info, stream);
+}
+
+int HttpStreamFactoryImpl::Request::RestartTunnelWithProxyAuth(
+ const string16& username,
+ const string16& password) {
+ // We're restarting the job, so ditch the old key. Note that we could actually
+ // keep it around and eliminate the DCHECK in set_spdy_session_key() that
+ // |spdy_session_key_| is NULL, but I prefer to keep the assertion.
+ RemoveRequestFromSpdySessionRequestMap();
+ return job_->RestartTunnelWithProxyAuth(username, password);
+}
+
+LoadState HttpStreamFactoryImpl::Request::GetLoadState() const {
+ return factory_->GetLoadState(*this);
+}
+
+bool HttpStreamFactoryImpl::Request::was_alternate_protocol_available() const {
+ DCHECK(completed_);
+ return was_alternate_protocol_available_;
+}
+
+bool HttpStreamFactoryImpl::Request::was_npn_negotiated() const {
+ DCHECK(completed_);
+ return was_npn_negotiated_;
+}
+
+bool HttpStreamFactoryImpl::Request::using_spdy() const {
+ DCHECK(completed_);
+ return using_spdy_;
+}
+
+void
+HttpStreamFactoryImpl::Request::RemoveRequestFromSpdySessionRequestMap() {
+ if (spdy_session_key_.get()) {
+ SpdySessionRequestMap& spdy_session_request_map =
+ factory_->spdy_session_request_map_;
+ DCHECK(ContainsKey(spdy_session_request_map, *spdy_session_key_));
+ RequestSet& request_set =
+ spdy_session_request_map[*spdy_session_key_];
+ DCHECK(ContainsKey(request_set, this));
+ request_set.erase(this);
+ if (request_set.empty())
+ spdy_session_request_map.erase(*spdy_session_key_);
+ spdy_session_key_.reset();
+ }
+}
+
+} // namespace net
diff --git a/net/http/http_stream_factory_impl_request.h b/net/http/http_stream_factory_impl_request.h
new file mode 100644
index 0000000..468ebd3
--- /dev/null
+++ b/net/http/http_stream_factory_impl_request.h
@@ -0,0 +1,94 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_HTTP_HTTP_STREAM_FACTORY_IMPL_REQUEST_H_
+#define NET_HTTP_HTTP_STREAM_FACTORY_IMPL_REQUEST_H_
+
+#include "base/scoped_ptr.h"
+#include "googleurl/src/gurl.h"
+#include "net/http/http_stream_factory_impl.h"
+
+namespace net {
+
+class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
+ public:
+ Request(const GURL& url,
+ HttpStreamFactoryImpl* factory,
+ HttpStreamRequest::Delegate* delegate);
+ virtual ~Request();
+
+ // Returns the Job that the Request started up.
+ Job* job() const { return job_; }
+
+ // The GURL from the HttpRequestInfo the started the Request.
+ const GURL& url() const { return url_; }
+
+ // Called when the Job determines the appropriate |spdy_session_key| for the
+ // Request. Note that this does not mean that SPDY is necessarily supported
+ // for this HostPortProxyPair, since we may need to wait for NPN to complete
+ // before knowing if SPDY is available.
+ void SetSpdySessionKey(const HostPortProxyPair& spdy_session_key);
+
+ // Binds |job| to this request.
+ void BindJob(HttpStreamFactoryImpl::Job* job);
+
+ // Marks completion of the request. Must be called before OnStreamReady().
+ void Complete(bool was_alternate_protocol_available,
+ bool was_npn_negotiated,
+ bool using_spdy);
+
+ // If this Request has a spdy_session_key, remove this session from the
+ // SpdySessionRequestMap.
+ void RemoveRequestFromSpdySessionRequestMap();
+
+ // HttpStreamRequest::Delegate methods which we implement. Note we don't
+ // actually subclass HttpStreamRequest::Delegate.
+
+ void OnStreamReady(const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ HttpStream* stream);
+ void OnStreamFailed(int status, const SSLConfig& used_ssl_config);
+ void OnCertificateError(int status,
+ const SSLConfig& used_ssl_config,
+ const SSLInfo& ssl_info);
+ void OnNeedsProxyAuth(const HttpResponseInfo& proxy_response,
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ HttpAuthController* auth_controller);
+ void OnNeedsClientAuth(const SSLConfig& used_ssl_config,
+ SSLCertRequestInfo* cert_info);
+ void OnHttpsProxyTunnelResponse(
+ const HttpResponseInfo& response_info,
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ HttpStream* stream);
+
+ // HttpStreamRequest methods.
+
+ virtual int RestartTunnelWithProxyAuth(const string16& username,
+ const string16& password);
+ virtual LoadState GetLoadState() const;
+ virtual bool was_alternate_protocol_available() const;
+ virtual bool was_npn_negotiated() const;
+ virtual bool using_spdy() const;
+
+ private:
+ const GURL url_;
+ HttpStreamFactoryImpl* const factory_;
+ HttpStreamRequest::Delegate* const delegate_;
+
+ // The |job_| that this request is tied to.
+ HttpStreamFactoryImpl::Job* job_;
+ scoped_ptr<const HostPortProxyPair> spdy_session_key_;
+
+ bool completed_;
+ bool was_alternate_protocol_available_;
+ bool was_npn_negotiated_;
+ bool using_spdy_;
+
+ DISALLOW_COPY_AND_ASSIGN(Request);
+};
+
+} // namespace net
+#endif // NET_HTTP_HTTP_STREAM_FACTORY_IMPL_H_
diff --git a/net/net.gyp b/net/net.gyp
index df9f2f8..bd14ccc 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -511,6 +511,8 @@
'http/http_stream_factory_impl.h',
'http/http_stream_factory_impl_job.cc',
'http/http_stream_factory_impl_job.h',
+ 'http/http_stream_factory_impl_request.cc',
+ 'http/http_stream_factory_impl_request.h',
'http/http_stream_parser.cc',
'http/http_stream_parser.h',
'http/http_transaction.h',
diff --git a/net/proxy/proxy_server.h b/net/proxy/proxy_server.h
index 3167252..c127aad 100644
--- a/net/proxy/proxy_server.h
+++ b/net/proxy/proxy_server.h
@@ -42,7 +42,7 @@ class ProxyServer {
bool is_valid() const { return scheme_ != SCHEME_INVALID; }
- // Gets the proxy's scheme (i.e. SOCKS4, SOCKS5, HTTP}
+ // Gets the proxy's scheme (i.e. SOCKS4, SOCKS5, HTTP)
Scheme scheme() const { return scheme_; }
// Returns true if this ProxyServer is actually just a DIRECT connection.
@@ -158,6 +158,8 @@ class ProxyServer {
HostPortPair host_port_pair_;
};
+typedef std::pair<HostPortPair, ProxyServer> HostPortProxyPair;
+
} // namespace net
#endif // NET_PROXY_PROXY_SERVER_H_
diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h
index 10da747..91ff8cb 100644
--- a/net/spdy/spdy_session_pool.h
+++ b/net/spdy/spdy_session_pool.h
@@ -23,9 +23,6 @@
#include "net/spdy/spdy_settings_storage.h"
namespace net {
-// Sessions are uniquely identified by their HostPortPair and the proxy server
-// that will be used to connect to it (may be DIRECT).
-typedef std::pair<HostPortPair, ProxyServer> HostPortProxyPair;
class BoundNetLog;
class ClientSocketHandle;