Index: net/http/http_stream_factory_impl_job.cc |
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc |
index eabbed0bba902d2475b00a21b1aff6706dadd966..a37c134818543d3e7fa2e57e12ff59f887ec0de2 100644 |
--- a/net/http/http_stream_factory_impl_job.cc |
+++ b/net/http/http_stream_factory_impl_job.cc |
@@ -42,6 +42,7 @@ |
#include "net/socket/socks_client_socket_pool.h" |
#include "net/socket/ssl_client_socket.h" |
#include "net/socket/ssl_client_socket_pool.h" |
+#include "net/spdy/bidirectional_stream_spdy_job.h" |
#include "net/spdy/spdy_http_stream.h" |
#include "net/spdy/spdy_protocol.h" |
#include "net/spdy/spdy_session.h" |
@@ -137,6 +138,7 @@ HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory, |
spdy_session_direct_(false), |
job_status_(STATUS_RUNNING), |
other_job_status_(STATUS_RUNNING), |
+ for_bidirectional_(false), |
ptr_factory_(this) { |
DCHECK(stream_factory); |
DCHECK(session); |
@@ -168,6 +170,8 @@ HttpStreamFactoryImpl::Job::~Job() { |
void HttpStreamFactoryImpl::Job::Start(Request* request) { |
DCHECK(request); |
request_ = request; |
+ // Saves |for_bidirectional_|, since request is nulled when job is orphaned. |
+ for_bidirectional_ = request_->for_bidirectional(); |
StartInternal(); |
} |
@@ -358,8 +362,25 @@ void HttpStreamFactoryImpl::Job::OnWebSocketHandshakeStreamReadyCallback() { |
// |this| may be deleted after this call. |
} |
+void HttpStreamFactoryImpl::Job::OnBidirectionalStreamJobReadyCallback() { |
+ DCHECK(bidirectional_stream_job_); |
+ |
+ MaybeCopyConnectionAttemptsFromSocketOrHandle(); |
+ |
+ if (IsOrphaned()) { |
+ stream_factory_->OnOrphanedJobComplete(this); |
+ } else { |
+ request_->Complete(was_npn_negotiated(), protocol_negotiated(), |
+ using_spdy()); |
+ request_->OnBidirectionalStreamJobReady( |
+ this, server_ssl_config_, proxy_info_, |
+ bidirectional_stream_job_.release()); |
+ } |
+ // |this| may be deleted after this call. |
+} |
+ |
void HttpStreamFactoryImpl::Job::OnNewSpdySessionReadyCallback() { |
- DCHECK(stream_.get()); |
+ DCHECK(stream_.get() || bidirectional_stream_job_.get()); |
DCHECK(!IsPreconnecting()); |
DCHECK(using_spdy()); |
// Note: an event loop iteration has passed, so |new_spdy_session_| may be |
@@ -379,8 +400,18 @@ void HttpStreamFactoryImpl::Job::OnNewSpdySessionReadyCallback() { |
} |
stream_factory_->OnOrphanedJobComplete(this); |
} else { |
- request_->OnNewSpdySessionReady( |
- this, stream_.Pass(), spdy_session, spdy_session_direct_); |
+ if (for_bidirectional_) { |
+ DCHECK(bidirectional_stream_job_); |
+ request_->OnNewSpdySessionReady(this, /*spdy_http_stream=*/nullptr, |
+ bidirectional_stream_job_.Pass(), |
+ spdy_session, spdy_session_direct_); |
+ |
+ } else { |
+ DCHECK(stream_); |
+ request_->OnNewSpdySessionReady(this, stream_.Pass(), |
+ /** bidirectional_stream_job=*/nullptr, |
+ spdy_session, spdy_session_direct_); |
+ } |
} |
// |this| may be deleted after this call. |
} |
@@ -567,6 +598,16 @@ int HttpStreamFactoryImpl::Job::RunLoop(int result) { |
base::ThreadTaskRunnerHandle::Get()->PostTask( |
FROM_HERE, base::Bind(&Job::OnWebSocketHandshakeStreamReadyCallback, |
ptr_factory_.GetWeakPtr())); |
+ } else if (for_bidirectional_) { |
+ if (!bidirectional_stream_job_) { |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, base::Bind(&Job::OnStreamFailedCallback, |
+ ptr_factory_.GetWeakPtr(), ERR_FAILED)); |
+ } else { |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, base::Bind(&Job::OnBidirectionalStreamJobReadyCallback, |
+ ptr_factory_.GetWeakPtr())); |
+ } |
} else { |
DCHECK(stream_.get()); |
base::ThreadTaskRunnerHandle::Get()->PostTask( |
@@ -1144,12 +1185,18 @@ int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) { |
return ERR_IO_PENDING; |
} |
-int HttpStreamFactoryImpl::Job::SetSpdyHttpStream( |
- base::WeakPtr<SpdySession> session, bool direct) { |
+int HttpStreamFactoryImpl::Job::SetSpdyHttpStreamOrBidirectionalStreamJob( |
+ base::WeakPtr<SpdySession> session, |
+ bool direct) { |
// TODO(ricea): Restore the code for WebSockets over SPDY once it's |
// implemented. |
if (stream_factory_->for_websockets_) |
return ERR_NOT_IMPLEMENTED; |
+ if (for_bidirectional_) { |
+ // TODO(xunjieli): Create QUIC's version of BidirectionalStreamJob. |
+ bidirectional_stream_job_.reset(new BidirectionalStreamSpdyJob(session)); |
+ return OK; |
+ } |
// TODO(willchan): Delete this code, because eventually, the |
// HttpStreamFactoryImpl will be creating all the SpdyHttpStreams, since it |
@@ -1203,7 +1250,8 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() { |
connection_->socket()->Disconnect(); |
connection_->Reset(); |
- int set_result = SetSpdyHttpStream(existing_spdy_session_, direct); |
+ int set_result = SetSpdyHttpStreamOrBidirectionalStreamJob( |
+ existing_spdy_session_, direct); |
existing_spdy_session_.reset(); |
return set_result; |
} |
@@ -1216,7 +1264,7 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() { |
return result; |
} |
if (spdy_session) { |
- return SetSpdyHttpStream(spdy_session, direct); |
+ return SetSpdyHttpStreamOrBidirectionalStreamJob(spdy_session, direct); |
} |
result = valid_spdy_session_pool_->CreateAvailableSessionFromSocket( |
@@ -1251,12 +1299,13 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() { |
if (http_server_properties) |
http_server_properties->SetSupportsSpdy(host_port_pair, true); |
- // Create a SpdyHttpStream attached to the session; |
- // OnNewSpdySessionReadyCallback is not called until an event loop |
+ // Create a SpdyHttpStream or a BidirectionalStreamJob attached to the |
+ // session; OnNewSpdySessionReadyCallback is not called until an event loop |
// iteration later, so if the SpdySession is closed between then, allow |
// reuse state from the underlying socket, sampled by SpdyHttpStream, |
// bubble up to the request. |
- return SetSpdyHttpStream(new_spdy_session_, spdy_session_direct_); |
+ return SetSpdyHttpStreamOrBidirectionalStreamJob(new_spdy_session_, |
+ spdy_session_direct_); |
} |
int HttpStreamFactoryImpl::Job::DoCreateStreamComplete(int result) { |