Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(410)

Unified Diff: net/http/http_stream_factory_impl.cc

Issue 2073293002: Revert of JobController 1: Remove cross reference between Request, Job, and Impl (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/http/http_stream_factory_impl.h ('k') | net/http/http_stream_factory_impl_job.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 ced9ce3d1dbac1f0bbd7d077a61d2d2facb25e7f..744b9807785c3bd325be7ae85c8e5a2a9c009ae6 100644
--- a/net/http/http_stream_factory_impl.cc
+++ b/net/http/http_stream_factory_impl.cc
@@ -7,13 +7,12 @@
#include <string>
#include "base/logging.h"
-#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.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"
@@ -24,59 +23,24 @@
namespace net {
-namespace {
-// Default JobFactory for creating HttpStreamFactoryImpl::Jobs.
-class DefaultJobFactory : public HttpStreamFactoryImpl::JobFactory {
- public:
- DefaultJobFactory() {}
-
- ~DefaultJobFactory() override {}
-
- HttpStreamFactoryImpl::Job* CreateJob(
- HttpStreamFactoryImpl::Job::Delegate* delegate,
- HttpStreamFactoryImpl::JobType job_type,
- HttpNetworkSession* session,
- const HttpRequestInfo& request_info,
- RequestPriority priority,
- const SSLConfig& server_ssl_config,
- const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
- GURL origin_url,
- NetLog* net_log) override {
- return new HttpStreamFactoryImpl::Job(
- delegate, job_type, session, request_info, priority, server_ssl_config,
- proxy_ssl_config, destination, origin_url, net_log);
- }
-
- HttpStreamFactoryImpl::Job* CreateJob(
- HttpStreamFactoryImpl::Job::Delegate* delegate,
- HttpStreamFactoryImpl::JobType job_type,
- HttpNetworkSession* session,
- const HttpRequestInfo& request_info,
- RequestPriority priority,
- const SSLConfig& server_ssl_config,
- const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
- GURL origin_url,
- AlternativeService alternative_service,
- NetLog* net_log) override {
- return new HttpStreamFactoryImpl::Job(
- delegate, job_type, session, request_info, priority, server_ssl_config,
- proxy_ssl_config, destination, origin_url, alternative_service,
- net_log);
- }
-};
-} // anonymous namespace
-
HttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session,
bool for_websockets)
: session_(session),
- job_factory_(new DefaultJobFactory()),
for_websockets_(for_websockets) {}
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());
}
HttpStreamRequest* HttpStreamFactoryImpl::RequestStream(
@@ -132,14 +96,48 @@
websocket_handshake_stream_create_helper,
HttpStreamRequest::StreamType stream_type,
const BoundNetLog& net_log) {
- JobController* job_controller =
- new JobController(this, delegate, session_, job_factory_.get());
- job_controller_set_.insert(base::WrapUnique(job_controller));
-
- Request* request = job_controller->Start(
- request_info, delegate, websocket_handshake_stream_create_helper, net_log,
- stream_type, priority, server_ssl_config, proxy_ssl_config);
-
+ 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);
+
+ 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);
+ }
+
+ // 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;
}
@@ -154,16 +152,188 @@
proxy_ssl_config.verify_ev_cert = true;
DCHECK(!for_websockets_);
-
- JobController* job_controller =
- new JobController(this, nullptr, session_, job_factory_.get());
- job_controller_set_.insert(base::WrapUnique(job_controller));
- job_controller->Preconnect(num_streams, request_info, server_ssl_config,
- proxy_ssl_config);
+ 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);
}
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) {
+ AlternativeService alternative_service =
+ GetAlternativeServiceForInternal(request_info, delegate, stream_type);
+ AlternativeServiceType type;
+ if (alternative_service.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) {
+ type = NO_ALTERNATIVE_SERVICE;
+ } else if (alternative_service.protocol == QUIC) {
+ if (request_info.url.host() == alternative_service.host) {
+ type = QUIC_SAME_DESTINATION;
+ } else {
+ type = QUIC_DIFFERENT_DESTINATION;
+ }
+ } else {
+ if (request_info.url.host() == alternative_service.host) {
+ type = NOT_QUIC_SAME_DESTINATION;
+ } else {
+ type = NOT_QUIC_DIFFERENT_DESTINATION;
+ }
+ }
+ UMA_HISTOGRAM_ENUMERATION("Net.AlternativeServiceTypeForRequest", type,
+ MAX_ALTERNATIVE_SERVICE_TYPE);
+ return alternative_service;
+}
+
+AlternativeService HttpStreamFactoryImpl::GetAlternativeServiceForInternal(
+ const HttpRequestInfo& request_info,
+ HttpStreamRequest::Delegate* delegate,
+ HttpStreamRequest::StreamType stream_type) {
+ GURL original_url = request_info.url;
+
+ if (original_url.SchemeIs("ftp"))
+ return AlternativeService();
+
+ if (!session_->params().enable_alternative_service_for_insecure_origins &&
+ !original_url.SchemeIs("https"))
+ 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;
+
+ // TODO(bnc): Re-enable when https://crbug.com/615413 is fixed.
+ if (origin.host() != alternative_service.host)
+ 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 mapped_origin(origin.host(), origin.port());
+ ignore_result(ApplyHostMappingRules(original_url, &mapped_origin));
+ QuicServerId server_id(mapped_origin, request_info.privacy_mode);
+
+ HostPortPair destination(alternative_service.host_port_pair());
+ ignore_result(ApplyHostMappingRules(original_url, &destination));
+
+ if (session_->quic_stream_factory()->CanUseExistingSession(server_id,
+ destination)) {
+ 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(
@@ -197,27 +367,47 @@
} else if (request->stream_type() ==
HttpStreamRequest::BIDIRECTIONAL_STREAM) {
request->OnBidirectionalStreamImplReady(
- used_ssl_config, used_proxy_info,
+ nullptr, used_ssl_config, used_proxy_info,
new BidirectionalStreamSpdyImpl(spdy_session));
} else {
bool use_relative_url = direct || request->url().SchemeIs("https");
request->OnStreamReady(
- used_ssl_config, used_proxy_info,
+ nullptr, used_ssl_config, used_proxy_info,
new SpdyHttpStream(spdy_session, use_relative_url));
}
}
// TODO(mbelshe): Alert other valid requests.
}
-void HttpStreamFactoryImpl::OnJobControllerComplete(JobController* controller) {
- for (auto it = job_controller_set_.begin(); it != job_controller_set_.end();
- ++it) {
- if (it->get() == controller) {
- job_controller_set_.erase(it);
- return;
- }
- }
- NOTREACHED();
+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;
+
+ return ContainsKey(session_->params().quic_host_whitelist,
+ base::ToLowerASCII(host));
}
} // namespace net
« no previous file with comments | « net/http/http_stream_factory_impl.h ('k') | net/http/http_stream_factory_impl_job.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698