| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_stream_factory_impl_job.h" | 5 #include "net/http/http_stream_factory_impl_job.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 request_->OnStreamReady(this, server_ssl_config_, proxy_info_, | 291 request_->OnStreamReady(this, server_ssl_config_, proxy_info_, |
| 292 stream_.release()); | 292 stream_.release()); |
| 293 } | 293 } |
| 294 // |this| may be deleted after this call. | 294 // |this| may be deleted after this call. |
| 295 } | 295 } |
| 296 | 296 |
| 297 void HttpStreamFactoryImpl::Job::OnSpdySessionReadyCallback() { | 297 void HttpStreamFactoryImpl::Job::OnSpdySessionReadyCallback() { |
| 298 DCHECK(!stream_.get()); | 298 DCHECK(!stream_.get()); |
| 299 DCHECK(!IsPreconnecting()); | 299 DCHECK(!IsPreconnecting()); |
| 300 DCHECK(using_spdy()); | 300 DCHECK(using_spdy()); |
| 301 DCHECK(new_spdy_session_); | 301 DCHECK(new_spdy_session_.get()); |
| 302 scoped_refptr<SpdySession> spdy_session = new_spdy_session_; | 302 scoped_refptr<SpdySession> spdy_session = new_spdy_session_; |
| 303 new_spdy_session_ = NULL; | 303 new_spdy_session_ = NULL; |
| 304 if (IsOrphaned()) { | 304 if (IsOrphaned()) { |
| 305 stream_factory_->OnSpdySessionReady( | 305 stream_factory_->OnSpdySessionReady( |
| 306 spdy_session, spdy_session_direct_, server_ssl_config_, proxy_info_, | 306 spdy_session, spdy_session_direct_, server_ssl_config_, proxy_info_, |
| 307 was_npn_negotiated(), protocol_negotiated(), using_spdy(), net_log_); | 307 was_npn_negotiated(), protocol_negotiated(), using_spdy(), net_log_); |
| 308 stream_factory_->OnOrphanedJobComplete(this); | 308 stream_factory_->OnOrphanedJobComplete(this); |
| 309 } else { | 309 } else { |
| 310 request_->OnSpdySessionReady(this, spdy_session, spdy_session_direct_); | 310 request_->OnSpdySessionReady(this, spdy_session, spdy_session_direct_); |
| 311 } | 311 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 if (IsOrphaned()) | 360 if (IsOrphaned()) |
| 361 stream_factory_->OnOrphanedJobComplete(this); | 361 stream_factory_->OnOrphanedJobComplete(this); |
| 362 else | 362 else |
| 363 request_->OnHttpsProxyTunnelResponse( | 363 request_->OnHttpsProxyTunnelResponse( |
| 364 this, response_info, server_ssl_config_, proxy_info_, stream); | 364 this, response_info, server_ssl_config_, proxy_info_, stream); |
| 365 // |this| may be deleted after this call. | 365 // |this| may be deleted after this call. |
| 366 } | 366 } |
| 367 | 367 |
| 368 void HttpStreamFactoryImpl::Job::OnPreconnectsComplete() { | 368 void HttpStreamFactoryImpl::Job::OnPreconnectsComplete() { |
| 369 DCHECK(!request_); | 369 DCHECK(!request_); |
| 370 if (new_spdy_session_) { | 370 if (new_spdy_session_.get()) { |
| 371 stream_factory_->OnSpdySessionReady( | 371 stream_factory_->OnSpdySessionReady(new_spdy_session_, |
| 372 new_spdy_session_, spdy_session_direct_, server_ssl_config_, | 372 spdy_session_direct_, |
| 373 proxy_info_, was_npn_negotiated(), protocol_negotiated(), using_spdy(), | 373 server_ssl_config_, |
| 374 net_log_); | 374 proxy_info_, |
| 375 was_npn_negotiated(), |
| 376 protocol_negotiated(), |
| 377 using_spdy(), |
| 378 net_log_); |
| 375 } | 379 } |
| 376 stream_factory_->OnPreconnectsComplete(this); | 380 stream_factory_->OnPreconnectsComplete(this); |
| 377 // |this| may be deleted after this call. | 381 // |this| may be deleted after this call. |
| 378 } | 382 } |
| 379 | 383 |
| 380 // static | 384 // static |
| 381 int HttpStreamFactoryImpl::Job::OnHostResolution( | 385 int HttpStreamFactoryImpl::Job::OnHostResolution( |
| 382 SpdySessionPool* spdy_session_pool, | 386 SpdySessionPool* spdy_session_pool, |
| 383 const SpdySessionKey& spdy_session_key, | 387 const SpdySessionKey& spdy_session_key, |
| 384 const AddressList& addresses, | 388 const AddressList& addresses, |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 base::Bind( | 477 base::Bind( |
| 474 &HttpStreamFactoryImpl::Job::OnHttpsProxyTunnelResponseCallback, | 478 &HttpStreamFactoryImpl::Job::OnHttpsProxyTunnelResponseCallback, |
| 475 ptr_factory_.GetWeakPtr(), | 479 ptr_factory_.GetWeakPtr(), |
| 476 *proxy_socket->GetConnectResponseInfo(), | 480 *proxy_socket->GetConnectResponseInfo(), |
| 477 proxy_socket->CreateConnectResponseStream())); | 481 proxy_socket->CreateConnectResponseStream())); |
| 478 return ERR_IO_PENDING; | 482 return ERR_IO_PENDING; |
| 479 } | 483 } |
| 480 | 484 |
| 481 case OK: | 485 case OK: |
| 482 next_state_ = STATE_DONE; | 486 next_state_ = STATE_DONE; |
| 483 if (new_spdy_session_) { | 487 if (new_spdy_session_.get()) { |
| 484 base::MessageLoop::current()->PostTask( | 488 base::MessageLoop::current()->PostTask( |
| 485 FROM_HERE, | 489 FROM_HERE, |
| 486 base::Bind( | 490 base::Bind(&HttpStreamFactoryImpl::Job::OnSpdySessionReadyCallback, |
| 487 &HttpStreamFactoryImpl::Job::OnSpdySessionReadyCallback, | 491 ptr_factory_.GetWeakPtr())); |
| 488 ptr_factory_.GetWeakPtr())); | |
| 489 } else { | 492 } else { |
| 490 base::MessageLoop::current()->PostTask( | 493 base::MessageLoop::current()->PostTask( |
| 491 FROM_HERE, | 494 FROM_HERE, |
| 492 base::Bind( | 495 base::Bind( |
| 493 &HttpStreamFactoryImpl::Job::OnStreamReadyCallback, | 496 &HttpStreamFactoryImpl::Job::OnStreamReadyCallback, |
| 494 ptr_factory_.GetWeakPtr())); | 497 ptr_factory_.GetWeakPtr())); |
| 495 } | 498 } |
| 496 return ERR_IO_PENDING; | 499 return ERR_IO_PENDING; |
| 497 | 500 |
| 498 default: | 501 default: |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 const ProxyServer& proxy_server = proxy_info_.proxy_server(); | 706 const ProxyServer& proxy_server = proxy_info_.proxy_server(); |
| 704 return quic_request_.Request(HostPortProxyPair(origin_, proxy_server), | 707 return quic_request_.Request(HostPortProxyPair(origin_, proxy_server), |
| 705 net_log_, io_callback_); | 708 net_log_, io_callback_); |
| 706 } | 709 } |
| 707 | 710 |
| 708 // Check first if we have a spdy session for this group. If so, then go | 711 // Check first if we have a spdy session for this group. If so, then go |
| 709 // straight to using that. | 712 // straight to using that. |
| 710 SpdySessionKey spdy_session_key = GetSpdySessionKey(); | 713 SpdySessionKey spdy_session_key = GetSpdySessionKey(); |
| 711 scoped_refptr<SpdySession> spdy_session = | 714 scoped_refptr<SpdySession> spdy_session = |
| 712 session_->spdy_session_pool()->GetIfExists(spdy_session_key, net_log_); | 715 session_->spdy_session_pool()->GetIfExists(spdy_session_key, net_log_); |
| 713 if (spdy_session && CanUseExistingSpdySession()) { | 716 if (spdy_session.get() && CanUseExistingSpdySession()) { |
| 714 // If we're preconnecting, but we already have a SpdySession, we don't | 717 // If we're preconnecting, but we already have a SpdySession, we don't |
| 715 // actually need to preconnect any sockets, so we're done. | 718 // actually need to preconnect any sockets, so we're done. |
| 716 if (IsPreconnecting()) | 719 if (IsPreconnecting()) |
| 717 return OK; | 720 return OK; |
| 718 using_spdy_ = true; | 721 using_spdy_ = true; |
| 719 next_state_ = STATE_CREATE_STREAM; | 722 next_state_ = STATE_CREATE_STREAM; |
| 720 existing_spdy_session_ = spdy_session; | 723 existing_spdy_session_ = spdy_session; |
| 721 return OK; | 724 return OK; |
| 722 } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) { | 725 } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) { |
| 723 // Update the spdy session key for the request that launched this job. | 726 // Update the spdy session key for the request that launched this job. |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 808 DCHECK_EQ(OK, result); | 811 DCHECK_EQ(OK, result); |
| 809 return OK; | 812 return OK; |
| 810 } | 813 } |
| 811 | 814 |
| 812 if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) { | 815 if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) { |
| 813 // We found a SPDY connection after resolving the host. This is | 816 // We found a SPDY connection after resolving the host. This is |
| 814 // probably an IP pooled connection. | 817 // probably an IP pooled connection. |
| 815 SpdySessionKey spdy_session_key = GetSpdySessionKey(); | 818 SpdySessionKey spdy_session_key = GetSpdySessionKey(); |
| 816 existing_spdy_session_ = | 819 existing_spdy_session_ = |
| 817 session_->spdy_session_pool()->GetIfExists(spdy_session_key, net_log_); | 820 session_->spdy_session_pool()->GetIfExists(spdy_session_key, net_log_); |
| 818 if (existing_spdy_session_) { | 821 if (existing_spdy_session_.get()) { |
| 819 using_spdy_ = true; | 822 using_spdy_ = true; |
| 820 next_state_ = STATE_CREATE_STREAM; | 823 next_state_ = STATE_CREATE_STREAM; |
| 821 } else { | 824 } else { |
| 822 // It is possible that the spdy session no longer exists. | 825 // It is possible that the spdy session no longer exists. |
| 823 ReturnToStateInitConnection(true /* close connection */); | 826 ReturnToStateInitConnection(true /* close connection */); |
| 824 } | 827 } |
| 825 return OK; | 828 return OK; |
| 826 } | 829 } |
| 827 | 830 |
| 828 // TODO(willchan): Make this a bit more exact. Maybe there are recoverable | 831 // TODO(willchan): Make this a bit more exact. Maybe there are recoverable |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 954 int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) { | 957 int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) { |
| 955 // This state indicates that the stream request is in a partially | 958 // This state indicates that the stream request is in a partially |
| 956 // completed state, and we've called back to the delegate for more | 959 // completed state, and we've called back to the delegate for more |
| 957 // information. | 960 // information. |
| 958 | 961 |
| 959 // We're always waiting here for the delegate to call us back. | 962 // We're always waiting here for the delegate to call us back. |
| 960 return ERR_IO_PENDING; | 963 return ERR_IO_PENDING; |
| 961 } | 964 } |
| 962 | 965 |
| 963 int HttpStreamFactoryImpl::Job::DoCreateStream() { | 966 int HttpStreamFactoryImpl::Job::DoCreateStream() { |
| 964 DCHECK(connection_->socket() || existing_spdy_session_ || | 967 DCHECK(connection_->socket() || existing_spdy_session_.get() || |
| 965 existing_available_pipeline_ || using_quic_); | 968 existing_available_pipeline_ || using_quic_); |
| 966 | 969 |
| 967 next_state_ = STATE_CREATE_STREAM_COMPLETE; | 970 next_state_ = STATE_CREATE_STREAM_COMPLETE; |
| 968 | 971 |
| 969 // We only set the socket motivation if we're the first to use | 972 // We only set the socket motivation if we're the first to use |
| 970 // this socket. Is there a race for two SPDY requests? We really | 973 // this socket. Is there a race for two SPDY requests? We really |
| 971 // need to plumb this through to the connect level. | 974 // need to plumb this through to the connect level. |
| 972 if (connection_->socket() && !connection_->is_reused()) | 975 if (connection_->socket() && !connection_->is_reused()) |
| 973 SetSocketMotivation(); | 976 SetSocketMotivation(); |
| 974 | 977 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 // If we don't have a direct SPDY session, and we're using an HTTPS | 1015 // If we don't have a direct SPDY session, and we're using an HTTPS |
| 1013 // proxy, then we might have a SPDY session to the proxy. | 1016 // proxy, then we might have a SPDY session to the proxy. |
| 1014 // We never use privacy mode for connection to proxy server. | 1017 // We never use privacy mode for connection to proxy server. |
| 1015 spdy_session_key = SpdySessionKey(proxy_server.host_port_pair(), | 1018 spdy_session_key = SpdySessionKey(proxy_server.host_port_pair(), |
| 1016 ProxyServer::Direct(), | 1019 ProxyServer::Direct(), |
| 1017 kPrivacyModeDisabled); | 1020 kPrivacyModeDisabled); |
| 1018 direct = false; | 1021 direct = false; |
| 1019 } | 1022 } |
| 1020 | 1023 |
| 1021 scoped_refptr<SpdySession> spdy_session; | 1024 scoped_refptr<SpdySession> spdy_session; |
| 1022 if (existing_spdy_session_) { | 1025 if (existing_spdy_session_.get()) { |
| 1023 // We picked up an existing session, so we don't need our socket. | 1026 // We picked up an existing session, so we don't need our socket. |
| 1024 if (connection_->socket()) | 1027 if (connection_->socket()) |
| 1025 connection_->socket()->Disconnect(); | 1028 connection_->socket()->Disconnect(); |
| 1026 connection_->Reset(); | 1029 connection_->Reset(); |
| 1027 spdy_session.swap(existing_spdy_session_); | 1030 spdy_session.swap(existing_spdy_session_); |
| 1028 } else { | 1031 } else { |
| 1029 SpdySessionPool* spdy_pool = session_->spdy_session_pool(); | 1032 SpdySessionPool* spdy_pool = session_->spdy_session_pool(); |
| 1030 spdy_session = spdy_pool->GetIfExists(spdy_session_key, net_log_); | 1033 spdy_session = spdy_pool->GetIfExists(spdy_session_key, net_log_); |
| 1031 if (!spdy_session) { | 1034 if (!spdy_session.get()) { |
| 1032 int error = spdy_pool->GetSpdySessionFromSocket( | 1035 int error = spdy_pool->GetSpdySessionFromSocket(spdy_session_key, |
| 1033 spdy_session_key, connection_.release(), net_log_, | 1036 connection_.release(), |
| 1034 spdy_certificate_error_, &new_spdy_session_, using_ssl_); | 1037 net_log_, |
| 1038 spdy_certificate_error_, |
| 1039 &new_spdy_session_, |
| 1040 using_ssl_); |
| 1035 if (error != OK) | 1041 if (error != OK) |
| 1036 return error; | 1042 return error; |
| 1037 const HostPortPair& host_port_pair = spdy_session_key.host_port_pair(); | 1043 const HostPortPair& host_port_pair = spdy_session_key.host_port_pair(); |
| 1038 HttpServerProperties* http_server_properties = | 1044 HttpServerProperties* http_server_properties = |
| 1039 session_->http_server_properties(); | 1045 session_->http_server_properties(); |
| 1040 if (http_server_properties) | 1046 if (http_server_properties) |
| 1041 http_server_properties->SetSupportsSpdy(host_port_pair, true); | 1047 http_server_properties->SetSupportsSpdy(host_port_pair, true); |
| 1042 spdy_session_direct_ = direct; | 1048 spdy_session_direct_ = direct; |
| 1043 return OK; | 1049 return OK; |
| 1044 } | 1050 } |
| 1045 } | 1051 } |
| 1046 | 1052 |
| 1047 if (spdy_session->IsClosed()) | 1053 if (spdy_session->IsClosed()) |
| 1048 return ERR_CONNECTION_CLOSED; | 1054 return ERR_CONNECTION_CLOSED; |
| 1049 | 1055 |
| 1050 // TODO(willchan): Delete this code, because eventually, the | 1056 // TODO(willchan): Delete this code, because eventually, the |
| 1051 // HttpStreamFactoryImpl will be creating all the SpdyHttpStreams, since it | 1057 // HttpStreamFactoryImpl will be creating all the SpdyHttpStreams, since it |
| 1052 // will know when SpdySessions become available. | 1058 // will know when SpdySessions become available. |
| 1053 | 1059 |
| 1054 bool use_relative_url = direct || request_info_.url.SchemeIs("https"); | 1060 bool use_relative_url = direct || request_info_.url.SchemeIs("https"); |
| 1055 stream_.reset(new SpdyHttpStream(spdy_session, use_relative_url)); | 1061 stream_.reset(new SpdyHttpStream(spdy_session.get(), use_relative_url)); |
| 1056 return OK; | 1062 return OK; |
| 1057 } | 1063 } |
| 1058 | 1064 |
| 1059 int HttpStreamFactoryImpl::Job::DoCreateStreamComplete(int result) { | 1065 int HttpStreamFactoryImpl::Job::DoCreateStreamComplete(int result) { |
| 1060 if (result < 0) | 1066 if (result < 0) |
| 1061 return result; | 1067 return result; |
| 1062 | 1068 |
| 1063 session_->proxy_service()->ReportSuccess(proxy_info_); | 1069 session_->proxy_service()->ReportSuccess(proxy_info_); |
| 1064 next_state_ = STATE_NONE; | 1070 next_state_ = STATE_NONE; |
| 1065 return OK; | 1071 return OK; |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1278 | 1284 |
| 1279 // Add the bad certificate to the set of allowed certificates in the | 1285 // Add the bad certificate to the set of allowed certificates in the |
| 1280 // SSL config object. This data structure will be consulted after calling | 1286 // SSL config object. This data structure will be consulted after calling |
| 1281 // RestartIgnoringLastError(). And the user will be asked interactively | 1287 // RestartIgnoringLastError(). And the user will be asked interactively |
| 1282 // before RestartIgnoringLastError() is ever called. | 1288 // before RestartIgnoringLastError() is ever called. |
| 1283 SSLConfig::CertAndStatus bad_cert; | 1289 SSLConfig::CertAndStatus bad_cert; |
| 1284 | 1290 |
| 1285 // |ssl_info_.cert| may be NULL if we failed to create | 1291 // |ssl_info_.cert| may be NULL if we failed to create |
| 1286 // X509Certificate for whatever reason, but normally it shouldn't | 1292 // X509Certificate for whatever reason, but normally it shouldn't |
| 1287 // happen, unless this code is used inside sandbox. | 1293 // happen, unless this code is used inside sandbox. |
| 1288 if (ssl_info_.cert == NULL || | 1294 if (ssl_info_.cert.get() == NULL || |
| 1289 !X509Certificate::GetDEREncoded(ssl_info_.cert->os_cert_handle(), | 1295 !X509Certificate::GetDEREncoded(ssl_info_.cert->os_cert_handle(), |
| 1290 &bad_cert.der_cert)) { | 1296 &bad_cert.der_cert)) { |
| 1291 return error; | 1297 return error; |
| 1292 } | 1298 } |
| 1293 bad_cert.cert_status = ssl_info_.cert_status; | 1299 bad_cert.cert_status = ssl_info_.cert_status; |
| 1294 server_ssl_config_.allowed_bad_certs.push_back(bad_cert); | 1300 server_ssl_config_.allowed_bad_certs.push_back(bad_cert); |
| 1295 | 1301 |
| 1296 int load_flags = request_info_.load_flags; | 1302 int load_flags = request_info_.load_flags; |
| 1297 if (session_->params().ignore_certificate_errors) | 1303 if (session_->params().ignore_certificate_errors) |
| 1298 load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS; | 1304 load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1369 (net::LOAD_MAIN_FRAME | net::LOAD_SUB_FRAME | net::LOAD_PREFETCH | | 1375 (net::LOAD_MAIN_FRAME | net::LOAD_SUB_FRAME | net::LOAD_PREFETCH | |
| 1370 net::LOAD_IS_DOWNLOAD)) { | 1376 net::LOAD_IS_DOWNLOAD)) { |
| 1371 // Avoid pipelining resources that may be streamed for a long time. | 1377 // Avoid pipelining resources that may be streamed for a long time. |
| 1372 return false; | 1378 return false; |
| 1373 } | 1379 } |
| 1374 return stream_factory_->http_pipelined_host_pool_.IsKeyEligibleForPipelining( | 1380 return stream_factory_->http_pipelined_host_pool_.IsKeyEligibleForPipelining( |
| 1375 *http_pipelining_key_.get()); | 1381 *http_pipelining_key_.get()); |
| 1376 } | 1382 } |
| 1377 | 1383 |
| 1378 } // namespace net | 1384 } // namespace net |
| OLD | NEW |