Chromium Code Reviews| Index: net/http/http_stream_factory_impl.cc |
| diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc |
| index bfc79227c5fdd171d9188ee0019a44988c11f543..c0ea3f0087395de6c609bb3e3d71e1cc8380674a 100644 |
| --- a/net/http/http_stream_factory_impl.cc |
| +++ b/net/http/http_stream_factory_impl.cc |
| @@ -7,11 +7,13 @@ |
| #include <string> |
| #include "base/logging.h" |
| +#include "base/memory/ptr_util.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string_util.h" |
| #include "net/http/http_network_session.h" |
| #include "net/http/http_server_properties.h" |
| #include "net/http/http_stream_factory_impl_job.h" |
| +#include "net/http/http_stream_factory_impl_job_controller.h" |
| #include "net/http/http_stream_factory_impl_request.h" |
| #include "net/http/transport_security_state.h" |
| #include "net/log/net_log.h" |
| @@ -30,16 +32,7 @@ HttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session, |
| HttpStreamFactoryImpl::~HttpStreamFactoryImpl() { |
| DCHECK(request_map_.empty()); |
| DCHECK(spdy_session_request_map_.empty()); |
| - |
| - std::set<const Job*> tmp_job_set; |
| - tmp_job_set.swap(orphaned_job_set_); |
| - STLDeleteContainerPointers(tmp_job_set.begin(), tmp_job_set.end()); |
| - DCHECK(orphaned_job_set_.empty()); |
| - |
| - tmp_job_set.clear(); |
| - tmp_job_set.swap(preconnect_job_set_); |
| - STLDeleteContainerPointers(tmp_job_set.begin(), tmp_job_set.end()); |
| - DCHECK(preconnect_job_set_.empty()); |
| + job_controller_set_.clear(); |
| } |
| HttpStreamRequest* HttpStreamFactoryImpl::RequestStream( |
| @@ -95,48 +88,13 @@ HttpStreamRequest* HttpStreamFactoryImpl::RequestStreamInternal( |
| websocket_handshake_stream_create_helper, |
| HttpStreamRequest::StreamType stream_type, |
| const BoundNetLog& net_log) { |
| - Request* request = new Request(request_info.url, this, delegate, |
| - websocket_handshake_stream_create_helper, |
| - net_log, stream_type); |
| - HostPortPair destination(HostPortPair::FromURL(request_info.url)); |
| - GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); |
| - |
| - Job* job = |
| - new Job(this, session_, request_info, priority, server_ssl_config, |
| - proxy_ssl_config, destination, origin_url, net_log.net_log()); |
| - request->AttachJob(job); |
| - |
| - const AlternativeService alternative_service = |
| - GetAlternativeServiceFor(request_info, delegate, stream_type); |
| - |
| - if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { |
| - // Never share connection with other jobs for FTP requests. |
| - DVLOG(1) << "Selected alternative service (host: " |
| - << alternative_service.host_port_pair().host() |
| - << " port: " << alternative_service.host_port_pair().port() << ")"; |
| - |
| - DCHECK(!request_info.url.SchemeIs("ftp")); |
| - HostPortPair alternative_destination(alternative_service.host_port_pair()); |
| - ignore_result( |
| - ApplyHostMappingRules(request_info.url, &alternative_destination)); |
| - |
| - Job* alternative_job = |
| - new Job(this, session_, request_info, priority, server_ssl_config, |
| - proxy_ssl_config, alternative_destination, origin_url, |
| - alternative_service, net_log.net_log()); |
| - request->AttachJob(alternative_job); |
| + JobController* job_controller = new JobController(this, delegate, session_); |
| + job_controller_set_.insert(base::WrapUnique(job_controller)); |
| - job->WaitFor(alternative_job); |
| - // Make sure to wait until we call WaitFor(), before starting |
| - // |alternative_job|, otherwise |alternative_job| will not notify |job| |
| - // appropriately. |
| - alternative_job->Start(request); |
| - } |
| + Request* request = job_controller->Start( |
| + request_info, delegate, websocket_handshake_stream_create_helper, net_log, |
| + stream_type, priority, server_ssl_config, proxy_ssl_config); |
| - // Even if |alternative_job| has already finished, it will not have notified |
| - // the request yet, since we defer that to the next iteration of the |
| - // MessageLoop, so starting |job| is always safe. |
| - job->Start(request); |
| return request; |
| } |
| @@ -151,155 +109,17 @@ void HttpStreamFactoryImpl::PreconnectStreams( |
| proxy_ssl_config.verify_ev_cert = true; |
| DCHECK(!for_websockets_); |
| - AlternativeService alternative_service = GetAlternativeServiceFor( |
| - request_info, nullptr, HttpStreamRequest::HTTP_STREAM); |
| - HostPortPair destination(HostPortPair::FromURL(request_info.url)); |
| - GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); |
| - if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { |
| - if (session_->params().quic_disable_preconnect_if_0rtt && |
| - alternative_service.protocol == QUIC && |
| - session_->quic_stream_factory()->ZeroRTTEnabledFor(QuicServerId( |
| - alternative_service.host_port_pair(), request_info.privacy_mode))) { |
| - return; |
| - } |
| - destination = alternative_service.host_port_pair(); |
| - ignore_result(ApplyHostMappingRules(request_info.url, &destination)); |
| - } |
| - // Due to how the socket pools handle priorities and idle sockets, only IDLE |
| - // priority currently makes sense for preconnects. The priority for |
| - // preconnects is currently ignored (see RequestSocketsForPool()), but could |
| - // be used at some point for proxy resolution or something. |
| - Job* job = new Job(this, session_, request_info, IDLE, server_ssl_config, |
| - proxy_ssl_config, destination, origin_url, |
| - alternative_service, session_->net_log()); |
| - preconnect_job_set_.insert(job); |
| - job->Preconnect(num_streams); |
| + |
| + JobController* job_controller = new JobController(this, nullptr, session_); |
| + job_controller_set_.insert(base::WrapUnique(job_controller)); |
| + job_controller->Preconnect(num_streams, request_info, server_ssl_config, |
| + proxy_ssl_config); |
| } |
| const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const { |
| return session_->params().host_mapping_rules; |
| } |
| -AlternativeService HttpStreamFactoryImpl::GetAlternativeServiceFor( |
| - const HttpRequestInfo& request_info, |
| - HttpStreamRequest::Delegate* delegate, |
| - HttpStreamRequest::StreamType stream_type) { |
| - GURL original_url = request_info.url; |
| - |
| - if (original_url.SchemeIs("ftp")) |
| - return AlternativeService(); |
| - |
| - url::SchemeHostPort origin(original_url); |
| - HttpServerProperties& http_server_properties = |
| - *session_->http_server_properties(); |
| - const AlternativeServiceVector alternative_service_vector = |
| - http_server_properties.GetAlternativeServices(origin); |
| - if (alternative_service_vector.empty()) |
| - return AlternativeService(); |
| - |
| - bool quic_advertised = false; |
| - bool quic_all_broken = true; |
| - |
| - const bool enable_different_host = |
| - session_->params().enable_alternative_service_with_different_host; |
| - |
| - // First Alt-Svc that is not marked as broken. |
| - AlternativeService first_alternative_service; |
| - |
| - for (const AlternativeService& alternative_service : |
| - alternative_service_vector) { |
| - DCHECK(IsAlternateProtocolValid(alternative_service.protocol)); |
| - if (!quic_advertised && alternative_service.protocol == QUIC) |
| - quic_advertised = true; |
| - if (http_server_properties.IsAlternativeServiceBroken( |
| - alternative_service)) { |
| - HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_BROKEN); |
| - continue; |
| - } |
| - |
| - if (origin.host() != alternative_service.host && !enable_different_host) |
| - continue; |
| - |
| - // Some shared unix systems may have user home directories (like |
| - // http://foo.com/~mike) which allow users to emit headers. This is a bad |
| - // idea already, but with Alternate-Protocol, it provides the ability for a |
| - // single user on a multi-user system to hijack the alternate protocol. |
| - // These systems also enforce ports <1024 as restricted ports. So don't |
| - // allow protocol upgrades to user-controllable ports. |
| - const int kUnrestrictedPort = 1024; |
| - if (!session_->params().enable_user_alternate_protocol_ports && |
| - (alternative_service.port >= kUnrestrictedPort && |
| - origin.port() < kUnrestrictedPort)) |
| - continue; |
| - |
| - if (alternative_service.protocol >= NPN_SPDY_MINIMUM_VERSION && |
| - alternative_service.protocol <= NPN_SPDY_MAXIMUM_VERSION) { |
| - if (!HttpStreamFactory::spdy_enabled()) |
| - continue; |
| - |
| - // Cache this entry if we don't have a non-broken Alt-Svc yet. |
| - if (first_alternative_service.protocol == |
| - UNINITIALIZED_ALTERNATE_PROTOCOL) |
| - first_alternative_service = alternative_service; |
| - continue; |
| - } |
| - |
| - DCHECK_EQ(QUIC, alternative_service.protocol); |
| - quic_all_broken = false; |
| - if (!session_->params().enable_quic) |
| - continue; |
| - |
| - if (!IsQuicWhitelistedForHost(origin.host())) |
| - continue; |
| - |
| - if (stream_type == HttpStreamRequest::BIDIRECTIONAL_STREAM && |
| - session_->params().quic_disable_bidirectional_streams) { |
| - continue; |
| - } |
| - |
| - if (session_->quic_stream_factory()->IsQuicDisabled( |
| - alternative_service.port)) |
| - continue; |
| - |
| - if (!original_url.SchemeIs("https")) |
| - continue; |
| - |
| - // Check whether there is an existing QUIC session to use for this origin. |
| - HostPortPair destination(alternative_service.host_port_pair()); |
| - ignore_result(ApplyHostMappingRules(original_url, &destination)); |
| - QuicServerId server_id(destination, request_info.privacy_mode); |
| - |
| - HostPortPair origin_copy(origin.host(), origin.port()); |
| - ignore_result(ApplyHostMappingRules(original_url, &origin_copy)); |
| - |
| - if (session_->quic_stream_factory()->CanUseExistingSession( |
| - server_id, origin_copy.host())) { |
| - return alternative_service; |
| - } |
| - |
| - // Cache this entry if we don't have a non-broken Alt-Svc yet. |
| - if (first_alternative_service.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) |
| - first_alternative_service = alternative_service; |
| - } |
| - |
| - // Ask delegate to mark QUIC as broken for the origin. |
| - if (quic_advertised && quic_all_broken && delegate != nullptr) |
| - delegate->OnQuicBroken(); |
| - |
| - return first_alternative_service; |
| -} |
| - |
| -void HttpStreamFactoryImpl::OrphanJob(Job* job, const Request* request) { |
| - DCHECK(ContainsKey(request_map_, job)); |
| - DCHECK_EQ(request_map_[job], request); |
| - DCHECK(!ContainsKey(orphaned_job_set_, job)); |
| - |
| - request_map_.erase(job); |
| - |
| - orphaned_job_set_.insert(job); |
| - job->Orphan(request); |
| -} |
| - |
| void HttpStreamFactoryImpl::OnNewSpdySessionReady( |
| const base::WeakPtr<SpdySession>& spdy_session, |
| bool direct, |
| @@ -331,47 +151,26 @@ void HttpStreamFactoryImpl::OnNewSpdySessionReady( |
| } else if (request->stream_type() == |
| HttpStreamRequest::BIDIRECTIONAL_STREAM) { |
| request->OnBidirectionalStreamImplReady( |
| - nullptr, used_ssl_config, used_proxy_info, |
| + used_ssl_config, used_proxy_info, |
| new BidirectionalStreamSpdyImpl(spdy_session)); |
| } else { |
| bool use_relative_url = direct || request->url().SchemeIs("https"); |
| request->OnStreamReady( |
| - nullptr, used_ssl_config, used_proxy_info, |
| + used_ssl_config, used_proxy_info, |
| new SpdyHttpStream(spdy_session, use_relative_url)); |
| } |
| } |
| // TODO(mbelshe): Alert other valid requests. |
| } |
| -void HttpStreamFactoryImpl::OnOrphanedJobComplete(const Job* job) { |
| - orphaned_job_set_.erase(job); |
| - delete job; |
| -} |
| - |
| -void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) { |
| - preconnect_job_set_.erase(job); |
| - delete job; |
| - OnPreconnectsCompleteInternal(); |
| -} |
| - |
| -bool HttpStreamFactoryImpl::IsQuicWhitelistedForHost(const std::string& host) { |
| - bool whitelist_needed = false; |
| - for (QuicVersion version : session_->params().quic_supported_versions) { |
| - if (version <= QUIC_VERSION_30) { |
| - whitelist_needed = true; |
| - break; |
| - } |
| - } |
| - |
| - // The QUIC whitelist is not needed in QUIC versions after 30. |
| - if (!whitelist_needed) |
| - return true; |
| - |
| - if (session_->params().transport_security_state->IsGooglePinnedHost(host)) |
| - return true; |
| +void HttpStreamFactoryImpl::OnJobControllerComplete(JobController* controller) { |
| + auto it = std::find_if(job_controller_set_.begin(), job_controller_set_.end(), |
| + [controller](const std::unique_ptr<JobController>& c) { |
| + return c.get() == controller; |
| + }); |
|
Ryan Hamilton
2016/05/13 20:50:40
holy cow, that is hideous :(
That's almost enough
Zhongyi Shi
2016/05/13 22:22:19
Done.
|
| + CHECK(it != job_controller_set_.end()); |
| - return ContainsKey(session_->params().quic_host_whitelist, |
| - base::ToLowerASCII(host)); |
| + job_controller_set_.erase(it); |
| } |
| } // namespace net |