| 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 8ac81e681e670de409449473ebfb84201a763235..2f3c9b1d386c134c0701085c0b7776c3fda87871 100644
|
| --- a/net/http/http_stream_factory_impl_job.cc
|
| +++ b/net/http/http_stream_factory_impl_job.cc
|
| @@ -153,8 +153,7 @@
|
| return std::move(dict);
|
| }
|
|
|
| -HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
|
| - JobType job_type,
|
| +HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory,
|
| HttpNetworkSession* session,
|
| const HttpRequestInfo& request_info,
|
| RequestPriority priority,
|
| @@ -163,8 +162,7 @@
|
| HostPortPair destination,
|
| GURL origin_url,
|
| NetLog* net_log)
|
| - : Job(delegate,
|
| - job_type,
|
| + : Job(stream_factory,
|
| session,
|
| request_info,
|
| priority,
|
| @@ -175,8 +173,7 @@
|
| AlternativeService(),
|
| net_log) {}
|
|
|
| -HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
|
| - JobType job_type,
|
| +HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory,
|
| HttpNetworkSession* session,
|
| const HttpRequestInfo& request_info,
|
| RequestPriority priority,
|
| @@ -186,7 +183,8 @@
|
| GURL origin_url,
|
| AlternativeService alternative_service,
|
| NetLog* net_log)
|
| - : request_info_(request_info),
|
| + : request_(NULL),
|
| + request_info_(request_info),
|
| priority_(priority),
|
| server_ssl_config_(server_ssl_config),
|
| proxy_ssl_config_(proxy_ssl_config),
|
| @@ -194,13 +192,12 @@
|
| io_callback_(base::Bind(&Job::OnIOComplete, base::Unretained(this))),
|
| connection_(new ClientSocketHandle),
|
| session_(session),
|
| + stream_factory_(stream_factory),
|
| next_state_(STATE_NONE),
|
| pac_request_(NULL),
|
| destination_(destination),
|
| origin_url_(origin_url),
|
| alternative_service_(alternative_service),
|
| - delegate_(delegate),
|
| - job_type_(job_type),
|
| blocking_job_(NULL),
|
| waiting_job_(NULL),
|
| using_ssl_(false),
|
| @@ -218,6 +215,7 @@
|
| other_job_status_(STATUS_RUNNING),
|
| stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM),
|
| ptr_factory_(this) {
|
| + DCHECK(stream_factory);
|
| DCHECK(session);
|
| if (IsSpdyAlternative() &&
|
| !session_->params().enable_alternative_service_for_insecure_origins) {
|
| @@ -248,9 +246,11 @@
|
| stream_->Close(true /* not reusable */);
|
| }
|
|
|
| -void HttpStreamFactoryImpl::Job::Start(
|
| - HttpStreamRequest::StreamType stream_type) {
|
| - stream_type_ = stream_type;
|
| +void HttpStreamFactoryImpl::Job::Start(Request* request) {
|
| + DCHECK(request);
|
| + request_ = request;
|
| + // Saves |stream_type_|, since request is nulled when job is orphaned.
|
| + stream_type_ = request_->stream_type();
|
| StartInternal();
|
| }
|
|
|
| @@ -329,7 +329,9 @@
|
| ResumeAfterDelay();
|
| }
|
|
|
| -void HttpStreamFactoryImpl::Job::Orphan() {
|
| +void HttpStreamFactoryImpl::Job::Orphan(const Request* request) {
|
| + DCHECK_EQ(request_, request);
|
| + request_ = NULL;
|
| net_log_.AddEvent(NetLog::TYPE_HTTP_STREAM_JOB_ORPHANED);
|
| if (blocking_job_) {
|
| // We've been orphaned, but there's a job we're blocked on. Don't bother
|
| @@ -337,20 +339,20 @@
|
| DCHECK(blocking_job_->waiting_job_);
|
| blocking_job_->waiting_job_ = NULL;
|
| blocking_job_ = NULL;
|
| - if (delegate_->for_websockets() && connection_ && connection_->socket()) {
|
| + if (stream_factory_->for_websockets_ &&
|
| + connection_ && connection_->socket()) {
|
| connection_->socket()->Disconnect();
|
| }
|
| - delegate_->OnOrphanedJobComplete(this);
|
| - } else if (delegate_->for_websockets()) {
|
| + stream_factory_->OnOrphanedJobComplete(this);
|
| + } else if (stream_factory_->for_websockets_) {
|
| // We cancel this job because a WebSocketHandshakeStream can't be created
|
| // without a WebSocketHandshakeStreamBase::CreateHelper which is stored in
|
| - // the Request class and isn't retrievable by this job.
|
| + // the Request class and isn't accessible from this job.
|
| if (connection_ && connection_->socket()) {
|
| connection_->socket()->Disconnect();
|
| }
|
| - delegate_->OnOrphanedJobComplete(this);
|
| - }
|
| - // |this| may be deleted after this call.
|
| + stream_factory_->OnOrphanedJobComplete(this);
|
| + }
|
| }
|
|
|
| void HttpStreamFactoryImpl::Job::SetPriority(RequestPriority priority) {
|
| @@ -418,27 +420,40 @@
|
|
|
| void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() {
|
| DCHECK(stream_.get());
|
| - DCHECK_NE(job_type_, PRECONNECT);
|
| - DCHECK(!delegate_->for_websockets());
|
| + DCHECK(!IsPreconnecting());
|
| + DCHECK(!stream_factory_->for_websockets_);
|
|
|
| UMA_HISTOGRAM_TIMES("Net.HttpStreamFactoryJob.StreamReadyCallbackTime",
|
| base::TimeTicks::Now() - job_stream_ready_start_time_);
|
|
|
| MaybeCopyConnectionAttemptsFromSocketOrHandle();
|
|
|
| - delegate_->OnStreamReady(this, server_ssl_config_, proxy_info_);
|
| + if (IsOrphaned()) {
|
| + stream_factory_->OnOrphanedJobComplete(this);
|
| + } else {
|
| + request_->Complete(was_npn_negotiated(), protocol_negotiated(),
|
| + using_spdy());
|
| + request_->OnStreamReady(this, server_ssl_config_, proxy_info_,
|
| + stream_.release());
|
| + }
|
| // |this| may be deleted after this call.
|
| }
|
|
|
| void HttpStreamFactoryImpl::Job::OnWebSocketHandshakeStreamReadyCallback() {
|
| DCHECK(websocket_stream_);
|
| - DCHECK_NE(job_type_, PRECONNECT);
|
| - DCHECK(delegate_->for_websockets());
|
| + DCHECK(!IsPreconnecting());
|
| + DCHECK(stream_factory_->for_websockets_);
|
| + // An orphaned WebSocket job will be closed immediately and
|
| + // never be ready.
|
| + DCHECK(!IsOrphaned());
|
|
|
| MaybeCopyConnectionAttemptsFromSocketOrHandle();
|
|
|
| - delegate_->OnWebSocketHandshakeStreamReady(
|
| - this, server_ssl_config_, proxy_info_, websocket_stream_.release());
|
| + request_->Complete(was_npn_negotiated(), protocol_negotiated(), using_spdy());
|
| + request_->OnWebSocketHandshakeStreamReady(this,
|
| + server_ssl_config_,
|
| + proxy_info_,
|
| + websocket_stream_.release());
|
| // |this| may be deleted after this call.
|
| }
|
|
|
| @@ -447,14 +462,21 @@
|
|
|
| MaybeCopyConnectionAttemptsFromSocketOrHandle();
|
|
|
| - delegate_->OnBidirectionalStreamImplReady(this, server_ssl_config_,
|
| - proxy_info_);
|
| - // |this| may be deleted after this call.
|
| + if (IsOrphaned()) {
|
| + stream_factory_->OnOrphanedJobComplete(this);
|
| + } else {
|
| + request_->Complete(was_npn_negotiated(), protocol_negotiated(),
|
| + using_spdy());
|
| + request_->OnBidirectionalStreamImplReady(
|
| + this, server_ssl_config_, proxy_info_,
|
| + bidirectional_stream_impl_.release());
|
| + }
|
| +// |this| may be deleted after this call.
|
| }
|
|
|
| void HttpStreamFactoryImpl::Job::OnNewSpdySessionReadyCallback() {
|
| DCHECK(stream_.get() || bidirectional_stream_impl_.get());
|
| - DCHECK_NE(job_type_, PRECONNECT);
|
| + DCHECK(!IsPreconnecting());
|
| DCHECK(using_spdy());
|
| // Note: an event loop iteration has passed, so |new_spdy_session_| may be
|
| // NULL at this point if the SpdySession closed immediately after creation.
|
| @@ -463,68 +485,107 @@
|
|
|
| MaybeCopyConnectionAttemptsFromSocketOrHandle();
|
|
|
| - delegate_->OnNewSpdySessionReady(this, spdy_session, spdy_session_direct_);
|
| -
|
| + // TODO(jgraettinger): Notify the factory, and let that notify |request_|,
|
| + // rather than notifying |request_| directly.
|
| + if (IsOrphaned()) {
|
| + if (spdy_session) {
|
| + stream_factory_->OnNewSpdySessionReady(
|
| + spdy_session, spdy_session_direct_, server_ssl_config_, proxy_info_,
|
| + was_npn_negotiated(), protocol_negotiated(), using_spdy(), net_log_);
|
| + }
|
| + stream_factory_->OnOrphanedJobComplete(this);
|
| + } else {
|
| + if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) {
|
| + DCHECK(bidirectional_stream_impl_);
|
| + request_->OnNewSpdySessionReady(this, /*spdy_http_stream=*/nullptr,
|
| + std::move(bidirectional_stream_impl_),
|
| + spdy_session, spdy_session_direct_);
|
| + } else {
|
| + DCHECK(stream_);
|
| + request_->OnNewSpdySessionReady(this, std::move(stream_),
|
| + /** bidirectional_stream_impl=*/nullptr,
|
| + spdy_session, spdy_session_direct_);
|
| + }
|
| + }
|
| // |this| may be deleted after this call.
|
| }
|
|
|
| void HttpStreamFactoryImpl::Job::OnStreamFailedCallback(int result) {
|
| - DCHECK_NE(job_type_, PRECONNECT);
|
| + DCHECK(!IsPreconnecting());
|
|
|
| MaybeCopyConnectionAttemptsFromSocketOrHandle();
|
|
|
| - SSLFailureState ssl_failure_state =
|
| - connection_ ? connection_->ssl_failure_state() : SSL_FAILURE_NONE;
|
| -
|
| - delegate_->OnStreamFailed(this, result, server_ssl_config_,
|
| - ssl_failure_state);
|
| + if (IsOrphaned()) {
|
| + stream_factory_->OnOrphanedJobComplete(this);
|
| + } else {
|
| + SSLFailureState ssl_failure_state =
|
| + connection_ ? connection_->ssl_failure_state() : SSL_FAILURE_NONE;
|
| + request_->OnStreamFailed(this, result, server_ssl_config_,
|
| + ssl_failure_state);
|
| + }
|
| // |this| may be deleted after this call.
|
| }
|
|
|
| void HttpStreamFactoryImpl::Job::OnCertificateErrorCallback(
|
| int result, const SSLInfo& ssl_info) {
|
| - DCHECK_NE(job_type_, PRECONNECT);
|
| + DCHECK(!IsPreconnecting());
|
|
|
| MaybeCopyConnectionAttemptsFromSocketOrHandle();
|
|
|
| - delegate_->OnCertificateError(this, result, server_ssl_config_, ssl_info);
|
| + if (IsOrphaned())
|
| + stream_factory_->OnOrphanedJobComplete(this);
|
| + else
|
| + request_->OnCertificateError(this, result, server_ssl_config_, ssl_info);
|
| // |this| may be deleted after this call.
|
| }
|
|
|
| void HttpStreamFactoryImpl::Job::OnNeedsProxyAuthCallback(
|
| const HttpResponseInfo& response,
|
| HttpAuthController* auth_controller) {
|
| - DCHECK_NE(job_type_, PRECONNECT);
|
| -
|
| - delegate_->OnNeedsProxyAuth(this, response, server_ssl_config_, proxy_info_,
|
| - auth_controller);
|
| + DCHECK(!IsPreconnecting());
|
| + if (IsOrphaned())
|
| + stream_factory_->OnOrphanedJobComplete(this);
|
| + else
|
| + request_->OnNeedsProxyAuth(
|
| + this, response, server_ssl_config_, proxy_info_, auth_controller);
|
| // |this| may be deleted after this call.
|
| }
|
|
|
| void HttpStreamFactoryImpl::Job::OnNeedsClientAuthCallback(
|
| SSLCertRequestInfo* cert_info) {
|
| - DCHECK_NE(job_type_, PRECONNECT);
|
| -
|
| - delegate_->OnNeedsClientAuth(this, server_ssl_config_, cert_info);
|
| + DCHECK(!IsPreconnecting());
|
| + if (IsOrphaned())
|
| + stream_factory_->OnOrphanedJobComplete(this);
|
| + else
|
| + request_->OnNeedsClientAuth(this, server_ssl_config_, cert_info);
|
| // |this| may be deleted after this call.
|
| }
|
|
|
| void HttpStreamFactoryImpl::Job::OnHttpsProxyTunnelResponseCallback(
|
| const HttpResponseInfo& response_info,
|
| HttpStream* stream) {
|
| - DCHECK_NE(job_type_, PRECONNECT);
|
| -
|
| - delegate_->OnHttpsProxyTunnelResponse(this, response_info, server_ssl_config_,
|
| - proxy_info_, stream);
|
| + DCHECK(!IsPreconnecting());
|
| + if (IsOrphaned())
|
| + stream_factory_->OnOrphanedJobComplete(this);
|
| + else
|
| + request_->OnHttpsProxyTunnelResponse(
|
| + this, response_info, server_ssl_config_, proxy_info_, stream);
|
| // |this| may be deleted after this call.
|
| }
|
|
|
| void HttpStreamFactoryImpl::Job::OnPreconnectsComplete() {
|
| + DCHECK(!request_);
|
| if (new_spdy_session_.get()) {
|
| - delegate_->OnNewSpdySessionReady(this, new_spdy_session_,
|
| - spdy_session_direct_);
|
| - }
|
| - delegate_->OnPreconnectsComplete(this);
|
| + stream_factory_->OnNewSpdySessionReady(new_spdy_session_,
|
| + spdy_session_direct_,
|
| + server_ssl_config_,
|
| + proxy_info_,
|
| + was_npn_negotiated(),
|
| + protocol_negotiated(),
|
| + using_spdy(),
|
| + net_log_);
|
| + }
|
| + stream_factory_->OnPreconnectsComplete(this);
|
| // |this| may be deleted after this call.
|
| }
|
|
|
| @@ -562,7 +623,7 @@
|
| // if there was one.
|
| DCHECK(result == OK || waiting_job_ == NULL);
|
|
|
| - if (job_type_ == PRECONNECT) {
|
| + if (IsPreconnecting()) {
|
| base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| FROM_HERE,
|
| base::Bind(&HttpStreamFactoryImpl::Job::OnPreconnectsComplete,
|
| @@ -634,7 +695,7 @@
|
| base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| FROM_HERE, base::Bind(&Job::OnNewSpdySessionReadyCallback,
|
| ptr_factory_.GetWeakPtr()));
|
| - } else if (delegate_->for_websockets()) {
|
| + } else if (stream_factory_->for_websockets_) {
|
| DCHECK(websocket_stream_);
|
| base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| FROM_HERE, base::Bind(&Job::OnWebSocketHandshakeStreamReadyCallback,
|
| @@ -746,16 +807,16 @@
|
| int HttpStreamFactoryImpl::Job::DoStart() {
|
| valid_spdy_session_pool_.reset(new ValidSpdySessionPool(
|
| session_->spdy_session_pool(), origin_url_, IsSpdyAlternative()));
|
| - const BoundNetLog* net_log = delegate_->GetNetLog(this);
|
| -
|
| - if (net_log) {
|
| - net_log_.BeginEvent(
|
| - NetLog::TYPE_HTTP_STREAM_JOB,
|
| - base::Bind(&NetLogHttpStreamJobCallback, net_log->source(),
|
| - &request_info_.url, &origin_url_, &alternative_service_,
|
| - priority_));
|
| - net_log->AddEvent(NetLog::TYPE_HTTP_STREAM_REQUEST_STARTED_JOB,
|
| - net_log_.source().ToEventParametersCallback());
|
| +
|
| + net_log_.BeginEvent(
|
| + NetLog::TYPE_HTTP_STREAM_JOB,
|
| + base::Bind(&NetLogHttpStreamJobCallback,
|
| + request_ ? request_->net_log().source() : NetLog::Source(),
|
| + &request_info_.url, &origin_url_, &alternative_service_,
|
| + priority_));
|
| + if (request_) {
|
| + request_->net_log().AddEvent(NetLog::TYPE_HTTP_STREAM_REQUEST_STARTED_JOB,
|
| + net_log_.source().ToEventParametersCallback());
|
| }
|
|
|
| // Don't connect to restricted ports.
|
| @@ -990,7 +1051,7 @@
|
| if (spdy_session) {
|
| // If we're preconnecting, but we already have a SpdySession, we don't
|
| // actually need to preconnect any sockets, so we're done.
|
| - if (job_type_ == PRECONNECT)
|
| + if (IsPreconnecting())
|
| return OK;
|
| using_spdy_ = true;
|
| next_state_ = STATE_CREATE_STREAM;
|
| @@ -998,10 +1059,9 @@
|
| return OK;
|
| }
|
| }
|
| - if (using_ssl_) {
|
| - // Ask |delegate_delegate_| to update the spdy session key for the request
|
| - // that launched this job.
|
| - delegate_->SetSpdySessionKey(this, spdy_session_key);
|
| + if (request_ && !request_->HasSpdySessionKey() && using_ssl_) {
|
| + // Update the spdy session key for the request that launched this job.
|
| + request_->SetSpdySessionKey(spdy_session_key);
|
| }
|
|
|
| // OK, there's no available SPDY session. Let |waiting_job_| resume if it's
|
| @@ -1026,8 +1086,8 @@
|
| }
|
| }
|
|
|
| - if (job_type_ == PRECONNECT) {
|
| - DCHECK(!delegate_->for_websockets());
|
| + if (IsPreconnecting()) {
|
| + DCHECK(!stream_factory_->for_websockets_);
|
| return PreconnectSocketsForHttpRequest(
|
| GetSocketGroup(), destination_, request_info_.extra_headers,
|
| request_info_.load_flags, priority_, session_, proxy_info_, expect_spdy,
|
| @@ -1042,7 +1102,7 @@
|
| ? base::Bind(&Job::OnHostResolution, session_->spdy_session_pool(),
|
| spdy_session_key, origin_url_)
|
| : OnHostResolutionCallback();
|
| - if (delegate_->for_websockets()) {
|
| + if (stream_factory_->for_websockets_) {
|
| // TODO(ricea): Re-enable NPN when WebSockets over SPDY is supported.
|
| SSLConfig websocket_server_ssl_config = server_ssl_config_;
|
| websocket_server_ssl_config.alpn_protos.clear();
|
| @@ -1067,7 +1127,7 @@
|
| waiting_job_->Resume(this, base::TimeDelta());
|
| waiting_job_ = NULL;
|
| }
|
| - if (job_type_ == PRECONNECT) {
|
| + if (IsPreconnecting()) {
|
| if (using_quic_)
|
| return result;
|
| DCHECK_EQ(OK, result);
|
| @@ -1252,7 +1312,7 @@
|
| bool direct) {
|
| // TODO(ricea): Restore the code for WebSockets over SPDY once it's
|
| // implemented.
|
| - if (delegate_->for_websockets())
|
| + if (stream_factory_->for_websockets_)
|
| return ERR_NOT_IMPLEMENTED;
|
| if (stream_type_ == HttpStreamRequest::BIDIRECTIONAL_STREAM) {
|
| bidirectional_stream_impl_.reset(new BidirectionalStreamSpdyImpl(session));
|
| @@ -1297,11 +1357,11 @@
|
| bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) &&
|
| (request_info_.url.SchemeIs("http") ||
|
| request_info_.url.SchemeIs("ftp"));
|
| - if (delegate_->for_websockets()) {
|
| - DCHECK_NE(job_type_, PRECONNECT);
|
| - DCHECK(delegate_->websocket_handshake_stream_create_helper());
|
| + if (stream_factory_->for_websockets_) {
|
| + DCHECK(request_);
|
| + DCHECK(request_->websocket_handshake_stream_create_helper());
|
| websocket_stream_.reset(
|
| - delegate_->websocket_handshake_stream_create_helper()
|
| + request_->websocket_handshake_stream_create_helper()
|
| ->CreateBasicStream(std::move(connection_), using_proxy));
|
| } else {
|
| stream_.reset(new HttpBasicStream(connection_.release(), using_proxy));
|
| @@ -1423,7 +1483,8 @@
|
| connection_->socket()->Disconnect();
|
| connection_->Reset();
|
|
|
| - delegate_->RemoveRequestFromSpdySessionRequestMapForJob(this);
|
| + if (request_)
|
| + request_->RemoveRequestFromSpdySessionRequestMap();
|
|
|
| next_state_ = STATE_INIT_CONNECTION;
|
| }
|
| @@ -1565,7 +1626,8 @@
|
| if (connection_->socket())
|
| connection_->socket()->Disconnect();
|
| connection_->Reset();
|
| - delegate_->RemoveRequestFromSpdySessionRequestMapForJob(this);
|
| + if (request_)
|
| + request_->RemoveRequestFromSpdySessionRequestMap();
|
| next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
|
| } else {
|
| // If ReconsiderProxyAfterError() failed synchronously, it means
|
| @@ -1614,6 +1676,15 @@
|
| void HttpStreamFactoryImpl::Job::SwitchToSpdyMode() {
|
| if (HttpStreamFactory::spdy_enabled())
|
| using_spdy_ = true;
|
| +}
|
| +
|
| +bool HttpStreamFactoryImpl::Job::IsPreconnecting() const {
|
| + DCHECK_GE(num_streams_, 0);
|
| + return num_streams_ > 0;
|
| +}
|
| +
|
| +bool HttpStreamFactoryImpl::Job::IsOrphaned() const {
|
| + return !IsPreconnecting() && !request_;
|
| }
|
|
|
| void HttpStreamFactoryImpl::Job::ReportJobSucceededForRequest() {
|
| @@ -1726,15 +1797,16 @@
|
| // connection attempts from the proper place.
|
| void HttpStreamFactoryImpl::Job::
|
| MaybeCopyConnectionAttemptsFromSocketOrHandle() {
|
| - if (!connection_)
|
| + if (IsOrphaned() || !connection_)
|
| return;
|
|
|
| - ConnectionAttempts socket_attempts = connection_->connection_attempts();
|
| if (connection_->socket()) {
|
| + ConnectionAttempts socket_attempts;
|
| connection_->socket()->GetConnectionAttempts(&socket_attempts);
|
| - }
|
| -
|
| - delegate_->AddConnectionAttemptsToRequest(this, socket_attempts);
|
| + request_->AddConnectionAttempts(socket_attempts);
|
| + } else {
|
| + request_->AddConnectionAttempts(connection_->connection_attempts());
|
| + }
|
| }
|
|
|
| } // namespace net
|
|
|