1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_stream_factory_job_controller.h"
6
7 #include <list>
8 #include <memory>
9 #include <string>
10 #include <utility>
11 #include <vector>
12
13 #include "base/containers/contains.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/memory/scoped_refptr.h"
17 #include "base/run_loop.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/test/bind.h"
20 #include "base/test/metrics/histogram_tester.h"
21 #include "base/test/scoped_feature_list.h"
22 #include "base/test/task_environment.h"
23 #include "base/test/test_mock_time_task_runner.h"
24 #include "base/threading/platform_thread.h"
25 #include "base/values.h"
26 #include "net/base/completion_once_callback.h"
27 #include "net/base/features.h"
28 #include "net/base/host_port_pair.h"
29 #include "net/base/proxy_chain.h"
30 #include "net/base/proxy_server.h"
31 #include "net/base/proxy_string_util.h"
32 #include "net/base/schemeful_site.h"
33 #include "net/base/session_usage.h"
34 #include "net/base/test_proxy_delegate.h"
35 #include "net/dns/mock_host_resolver.h"
36 #include "net/dns/public/secure_dns_policy.h"
37 #include "net/http/alternative_service.h"
38 #include "net/http/http_basic_stream.h"
39 #include "net/http/http_network_session_peer.h"
40 #include "net/http/http_response_headers.h"
41 #include "net/http/http_server_properties.h"
42 #include "net/http/http_server_properties_manager.h"
43 #include "net/http/http_stream_factory.h"
44 #include "net/http/http_stream_factory_job.h"
45 #include "net/http/http_stream_factory_test_util.h"
46 #include "net/log/net_log.h"
47 #include "net/log/net_log_with_source.h"
48 #include "net/log/test_net_log.h"
49 #include "net/log/test_net_log_util.h"
50 #include "net/proxy_resolution/configured_proxy_resolution_service.h"
51 #include "net/proxy_resolution/mock_proxy_resolver.h"
52 #include "net/proxy_resolution/proxy_config_service_fixed.h"
53 #include "net/proxy_resolution/proxy_info.h"
54 #include "net/proxy_resolution/proxy_list.h"
55 #include "net/proxy_resolution/proxy_resolution_service.h"
56 #include "net/quic/crypto/proof_verifier_chromium.h"
57 #include "net/quic/mock_crypto_client_stream_factory.h"
58 #include "net/quic/mock_quic_context.h"
59 #include "net/quic/mock_quic_data.h"
60 #include "net/quic/quic_http_stream.h"
61 #include "net/quic/quic_session_pool.h"
62 #include "net/quic/quic_session_pool_peer.h"
63 #include "net/quic/quic_test_packet_maker.h"
64 #include "net/socket/socket_test_util.h"
65 #include "net/spdy/spdy_session_key.h"
66 #include "net/spdy/spdy_test_util_common.h"
67 #include "net/test/cert_test_util.h"
68 #include "net/test/test_data_directory.h"
69 #include "net/test/test_with_task_environment.h"
70 #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
71 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
72 #include "testing/gmock/include/gmock/gmock.h"
73 #include "testing/gtest/include/gtest/gtest.h"
74 #include "url/gurl.h"
75 #include "url/scheme_host_port.h"
76
77 using ::testing::_;
78 using ::testing::Contains;
79 using ::testing::ElementsAre;
80 using ::testing::Invoke;
81 using ::testing::IsEmpty;
82 using ::testing::Key;
83 using ::testing::SizeIs;
84
85 namespace net::test {
86
87 namespace {
88
89 const char kServerHostname[] = "www.example.com";
90
91 // The default delay for main job defined in QuicSessionPool::
92 // GetTimeDelayForWaitingJob().
93 const int kDefaultDelayMilliSecsForWaitingJob = 300;
94
95 class FailingProxyResolverFactory : public ProxyResolverFactory {
96 public:
FailingProxyResolverFactory()97 FailingProxyResolverFactory() : ProxyResolverFactory(false) {}
98
99 // ProxyResolverFactory override.
CreateProxyResolver(const scoped_refptr<PacFileData> & script_data,std::unique_ptr<ProxyResolver> * result,CompletionOnceCallback callback,std::unique_ptr<Request> * request)100 int CreateProxyResolver(const scoped_refptr<PacFileData>& script_data,
101 std::unique_ptr<ProxyResolver>* result,
102 CompletionOnceCallback callback,
103 std::unique_ptr<Request>* request) override {
104 return ERR_PAC_SCRIPT_FAILED;
105 }
106 };
107
108 // A mock HttpServerProperties::PrefDelegate that never finishes loading, so
109 // HttpServerProperties::IsInitialized() always returns false.
110 class MockPrefDelegate : public HttpServerProperties::PrefDelegate {
111 public:
112 MockPrefDelegate() = default;
113
114 MockPrefDelegate(const MockPrefDelegate&) = delete;
115 MockPrefDelegate& operator=(const MockPrefDelegate&) = delete;
116
117 ~MockPrefDelegate() override = default;
118
119 // HttpServerProperties::PrefDelegate implementation:
GetServerProperties() const120 const base::Value::Dict& GetServerProperties() const override {
121 return empty_dict_;
122 }
SetServerProperties(base::Value::Dict dict,base::OnceClosure callback)123 void SetServerProperties(base::Value::Dict dict,
124 base::OnceClosure callback) override {}
WaitForPrefLoad(base::OnceClosure pref_loaded_callback)125 void WaitForPrefLoad(base::OnceClosure pref_loaded_callback) override {}
126
127 base::Value::Dict empty_dict_;
128 };
129
130 // A `TestProxyDelegate` which always sets a `ProxyChain` with
131 // `is_for_ip_protection` set to true on the `ProxyInfo` it receives in
132 // `OnResolveProxy()`.
133 class TestProxyDelegateForIpProtection : public TestProxyDelegate {
134 public:
TestProxyDelegateForIpProtection()135 TestProxyDelegateForIpProtection() {
136 set_proxy_chain(net::ProxyChain::ForIpProtection(
137 {net::ProxyServer::FromSchemeHostAndPort(ProxyServer::SCHEME_HTTPS,
138 "ip-pro", 443)}));
139 set_extra_header_name(net::HttpRequestHeaders::kAuthorization);
140 }
OnResolveProxy(const GURL & url,const NetworkAnonymizationKey & network_anonymization_key,const std::string & method,const ProxyRetryInfoMap & proxy_retry_info,ProxyInfo * result)141 void OnResolveProxy(const GURL& url,
142 const NetworkAnonymizationKey& network_anonymization_key,
143 const std::string& method,
144 const ProxyRetryInfoMap& proxy_retry_info,
145 ProxyInfo* result) override {
146 net::ProxyList proxy_list;
147 proxy_list.AddProxyChain(proxy_chain());
148 proxy_list.AddProxyChain(net::ProxyChain::Direct());
149 result->UseProxyList(proxy_list);
150 }
151 };
152
153 } // anonymous namespace
154
155 class HttpStreamFactoryJobPeer {
156 public:
157 // Returns |num_streams_| of |job|. It should be 0 for non-preconnect Jobs.
GetNumStreams(const HttpStreamFactory::Job * job)158 static int GetNumStreams(const HttpStreamFactory::Job* job) {
159 return job->num_streams_;
160 }
161
162 // Return SpdySessionKey of |job|.
GetSpdySessionKey(const HttpStreamFactory::Job * job)163 static const SpdySessionKey GetSpdySessionKey(
164 const HttpStreamFactory::Job* job) {
165 return job->spdy_session_key_;
166 }
167
SetShouldReconsiderProxy(HttpStreamFactory::Job * job)168 static void SetShouldReconsiderProxy(HttpStreamFactory::Job* job) {
169 job->should_reconsider_proxy_ = true;
170 }
171
SetStream(HttpStreamFactory::Job * job,std::unique_ptr<HttpStream> http_stream)172 static void SetStream(HttpStreamFactory::Job* job,
173 std::unique_ptr<HttpStream> http_stream) {
174 job->stream_ = std::move(http_stream);
175 }
176
SetQuicConnectionFailedOnDefaultNetwork(HttpStreamFactory::Job * job)177 static void SetQuicConnectionFailedOnDefaultNetwork(
178 HttpStreamFactory::Job* job) {
179 job->quic_request_.OnConnectionFailedOnDefaultNetwork();
180 }
181 };
182
183 class JobControllerPeer {
184 public:
main_job_is_blocked(HttpStreamFactory::JobController * job_controller)185 static bool main_job_is_blocked(
186 HttpStreamFactory::JobController* job_controller) {
187 return job_controller->main_job_is_blocked_;
188 }
189
main_job_is_resumed(HttpStreamFactory::JobController * job_controller)190 static bool main_job_is_resumed(
191 HttpStreamFactory::JobController* job_controller) {
192 return job_controller->main_job_is_resumed_;
193 }
194
InitializeProxyInfo(HttpStreamFactory::JobController * job_controller)195 static void InitializeProxyInfo(
196 HttpStreamFactory::JobController* job_controller) {
197 job_controller->proxy_info_.UseDirect();
198 }
199
GetAlternativeServiceInfoFor(HttpStreamFactory::JobController * job_controller,const HttpRequestInfo & request_info,HttpStreamRequest::Delegate * delegate,HttpStreamRequest::StreamType stream_type)200 static AlternativeServiceInfo GetAlternativeServiceInfoFor(
201 HttpStreamFactory::JobController* job_controller,
202 const HttpRequestInfo& request_info,
203 HttpStreamRequest::Delegate* delegate,
204 HttpStreamRequest::StreamType stream_type) {
205 return job_controller->GetAlternativeServiceInfoFor(
206 request_info.url, HttpStreamFactory::StreamRequestInfo(request_info),
207 delegate, stream_type);
208 }
209
SelectQuicVersion(HttpStreamFactory::JobController * job_controller,const quic::ParsedQuicVersionVector & advertised_versions)210 static quic::ParsedQuicVersion SelectQuicVersion(
211 HttpStreamFactory::JobController* job_controller,
212 const quic::ParsedQuicVersionVector& advertised_versions) {
213 return job_controller->SelectQuicVersion(advertised_versions);
214 }
215
SetAltJobFailedOnDefaultNetwork(HttpStreamFactory::JobController * job_controller)216 static void SetAltJobFailedOnDefaultNetwork(
217 HttpStreamFactory::JobController* job_controller) {
218 DCHECK(job_controller->alternative_job() != nullptr);
219 HttpStreamFactoryJobPeer::SetQuicConnectionFailedOnDefaultNetwork(
220 job_controller->alternative_job_.get());
221 }
SetDnsAlpnH3JobFailedOnDefaultNetwork(HttpStreamFactory::JobController * job_controller)222 static void SetDnsAlpnH3JobFailedOnDefaultNetwork(
223 HttpStreamFactory::JobController* job_controller) {
224 DCHECK(job_controller->dns_alpn_h3_job() != nullptr);
225 HttpStreamFactoryJobPeer::SetQuicConnectionFailedOnDefaultNetwork(
226 job_controller->dns_alpn_h3_job_.get());
227 }
228 };
229
230 class HttpStreamFactoryJobControllerTestBase : public TestWithTaskEnvironment {
231 public:
HttpStreamFactoryJobControllerTestBase(bool dns_https_alpn_enabled,std::vector<base::test::FeatureRef> enabled_features={})232 explicit HttpStreamFactoryJobControllerTestBase(
233 bool dns_https_alpn_enabled,
234 std::vector<base::test::FeatureRef> enabled_features = {})
235 : TestWithTaskEnvironment(
236 base::test::TaskEnvironment::TimeSource::MOCK_TIME),
237 dns_https_alpn_enabled_(dns_https_alpn_enabled) {
238 std::vector<base::test::FeatureRef> disabled_features;
239 if (dns_https_alpn_enabled_) {
240 enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn);
241 } else {
242 disabled_features.push_back(features::kUseDnsHttpsSvcbAlpn);
243 }
244 feature_list_.InitWithFeatures(enabled_features, disabled_features);
245 FLAGS_quic_enable_http3_grease_randomness = false;
246 CreateSessionDeps();
247 }
248
249 // Creates / re-creates `session_deps_`, and clears test fixture fields
250 // referencing it.
CreateSessionDeps()251 void CreateSessionDeps() {
252 factory_ = nullptr;
253 job_controller_ = nullptr;
254 session_.reset();
255
256 session_deps_.proxy_resolution_service->SetProxyDelegate(nullptr);
257
258 session_deps_ = SpdySessionDependencies(
259 ConfiguredProxyResolutionService::CreateDirect());
260 session_deps_.enable_quic = true;
261 session_deps_.host_resolver->set_synchronous_mode(true);
262 }
263
SetPreconnect()264 void SetPreconnect() {
265 ASSERT_FALSE(session_deps_.proxy_delegate);
266 is_preconnect_ = true;
267 }
268
DisableIPBasedPooling()269 void DisableIPBasedPooling() {
270 ASSERT_FALSE(session_deps_.proxy_delegate);
271 enable_ip_based_pooling_ = false;
272 }
273
SetNotDelayMainJobWithAvailableSpdySession()274 void SetNotDelayMainJobWithAvailableSpdySession() {
275 ASSERT_FALSE(session_deps_.proxy_delegate);
276 delay_main_job_with_available_spdy_session_ = false;
277 }
278
DisableAlternativeServices()279 void DisableAlternativeServices() {
280 ASSERT_FALSE(session_deps_.proxy_delegate);
281 enable_alternative_services_ = false;
282 }
283
SkipCreatingJobController()284 void SkipCreatingJobController() {
285 ASSERT_FALSE(job_controller_);
286 create_job_controller_ = false;
287 }
288
Initialize(const HttpRequestInfo & request_info)289 void Initialize(const HttpRequestInfo& request_info) {
290 ASSERT_FALSE(session_deps_.proxy_delegate);
291 session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
292
293 if (quic_data_) {
294 quic_data_->AddSocketDataToFactory(session_deps_.socket_factory.get());
295 }
296 if (quic_data2_) {
297 quic_data2_->AddSocketDataToFactory(session_deps_.socket_factory.get());
298 }
299 if (tcp_data_) {
300 session_deps_.socket_factory->AddSocketDataProvider(tcp_data_.get());
301 }
302 if (tcp_data2_) {
303 session_deps_.socket_factory->AddSocketDataProvider(tcp_data2_.get());
304 }
305
306 session_deps_.proxy_resolution_service->SetProxyDelegate(
307 session_deps_.proxy_delegate.get());
308
309 session_deps_.net_log = NetLog::Get();
310 HttpNetworkSessionParams params =
311 SpdySessionDependencies::CreateSessionParams(&session_deps_);
312 HttpNetworkSessionContext session_context =
313 SpdySessionDependencies::CreateSessionContext(&session_deps_);
314
315 session_context.quic_crypto_client_stream_factory =
316 &crypto_client_stream_factory_;
317 session_context.quic_context = &quic_context_;
318 session_ = std::make_unique<HttpNetworkSession>(params, session_context);
319 factory_ = static_cast<HttpStreamFactory*>(session_->http_stream_factory());
320 if (create_job_controller_) {
321 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
322 factory_, &request_delegate_, session_.get(), &job_factory_,
323 request_info, is_preconnect_, /*is_websocket=*/false,
324 enable_ip_based_pooling_, enable_alternative_services_,
325 delay_main_job_with_available_spdy_session_,
326 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
327 job_controller_ = job_controller.get();
328 HttpStreamFactoryPeer::AddJobController(factory_,
329 std::move(job_controller));
330 }
331 }
332
333 HttpStreamFactoryJobControllerTestBase(
334 const HttpStreamFactoryJobControllerTestBase&) = delete;
335 HttpStreamFactoryJobControllerTestBase& operator=(
336 const HttpStreamFactoryJobControllerTestBase&) = delete;
337
~HttpStreamFactoryJobControllerTestBase()338 ~HttpStreamFactoryJobControllerTestBase() override {
339 if (should_check_data_consumed_) {
340 if (quic_data_) {
341 EXPECT_TRUE(quic_data_->AllReadDataConsumed());
342 EXPECT_TRUE(quic_data_->AllWriteDataConsumed());
343 }
344 if (quic_data2_) {
345 EXPECT_TRUE(quic_data2_->AllReadDataConsumed());
346 EXPECT_TRUE(quic_data2_->AllWriteDataConsumed());
347 }
348 if (tcp_data_) {
349 EXPECT_TRUE(tcp_data_->AllReadDataConsumed());
350 EXPECT_TRUE(tcp_data_->AllWriteDataConsumed());
351 }
352 if (tcp_data2_) {
353 EXPECT_TRUE(tcp_data2_->AllReadDataConsumed());
354 EXPECT_TRUE(tcp_data2_->AllWriteDataConsumed());
355 }
356 }
357 }
358
SetAlternativeService(const HttpRequestInfo & request_info,AlternativeService alternative_service)359 void SetAlternativeService(const HttpRequestInfo& request_info,
360 AlternativeService alternative_service) {
361 url::SchemeHostPort server(request_info.url);
362 base::Time expiration = base::Time::Now() + base::Days(1);
363 if (alternative_service.protocol == kProtoQUIC) {
364 session_->http_server_properties()->SetQuicAlternativeService(
365 server, NetworkAnonymizationKey(), alternative_service, expiration,
366 quic_context_.params()->supported_versions);
367 } else {
368 session_->http_server_properties()->SetHttp2AlternativeService(
369 server, NetworkAnonymizationKey(), alternative_service, expiration);
370 }
371 }
372
VerifyBrokenAlternateProtocolMapping(const HttpRequestInfo & request_info,bool should_mark_broken)373 void VerifyBrokenAlternateProtocolMapping(const HttpRequestInfo& request_info,
374 bool should_mark_broken) {
375 const url::SchemeHostPort server(request_info.url);
376 const AlternativeServiceInfoVector alternative_service_info_vector =
377 session_->http_server_properties()->GetAlternativeServiceInfos(
378 server, NetworkAnonymizationKey());
379 EXPECT_EQ(1u, alternative_service_info_vector.size());
380 EXPECT_EQ(should_mark_broken,
381 session_->http_server_properties()->IsAlternativeServiceBroken(
382 alternative_service_info_vector[0].alternative_service(),
383 NetworkAnonymizationKey()));
384 }
385
SetAsyncQuicSession(bool async_quic_session)386 void SetAsyncQuicSession(bool async_quic_session) {
387 std::vector<base::test::FeatureRef> enabled_features = {};
388 if (dns_https_alpn_enabled_) {
389 enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn);
390 }
391 if (async_quic_session) {
392 feature_list_.Reset();
393 enabled_features.push_back(features::kAsyncQuicSession);
394 feature_list_.InitWithFeatures(enabled_features, {});
395 } else {
396 feature_list_.Reset();
397 feature_list_.InitWithFeatures(enabled_features,
398 {features::kAsyncQuicSession});
399 }
400 }
401
402 void TestAltJobSucceedsAfterMainJobFailed(
403 bool alt_job_retried_on_non_default_network,
404 bool async_quic_session);
405 void TestMainJobSucceedsAfterAltJobFailed(
406 bool alt_job_retried_on_non_default_network,
407 bool async_quic_session);
408 void TestMainJobSucceedsAfterIgnoredError(int net_error,
409 bool async_quic_session,
410 bool expect_broken = false,
411 std::string alternate_host = "");
412 void TestAltJobSucceedsAfterMainJobSucceeded(
413 bool alt_job_retried_on_non_default_network,
414 bool async_quic_session);
415 void TestOnStreamFailedForBothJobs(
416 bool alt_job_retried_on_non_default_network,
417 bool async_quic_session);
418 void TestAltJobFailsAfterMainJobSucceeded(
419 bool alt_job_retried_on_non_default_network,
420 bool async_quic_session);
421 void TestMainJobSucceedsAfterAltJobSucceeded(
422 bool alt_job_retried_on_non_default_network,
423 bool async_quic_session);
424 void TestMainJobFailsAfterAltJobSucceeded(
425 bool alt_job_retried_on_non_default_network,
426 bool async_quic_session);
427 void TestAltSvcVersionSelection(
428 const std::string& alt_svc_header,
429 const quic::ParsedQuicVersion& expected_version,
430 const quic::ParsedQuicVersionVector& supported_versions);
431 void TestResumeMainJobWhenAltJobStalls(bool async_quic_session);
432 void TestAltJobSucceedsMainJobDestroyed(bool async_quic_session);
433 void TestOrphanedJobCompletesControllerDestroyed(bool async_quic_session);
434 void TestDoNotDelayMainJobIfQuicWasRecentlyBroken(bool async_quic_session);
435 void TestDelayMainJobAfterRecentlyBrokenQuicWasConfirmed(
436 bool async_quic_session);
437 void TestDoNotDelayMainJobIfHasAvailableSpdySession(bool async_quic_session);
438
dns_https_alpn_enabled() const439 bool dns_https_alpn_enabled() const { return dns_https_alpn_enabled_; }
440
441 quic::ParsedQuicVersion version_ = DefaultSupportedQuicVersions().front();
442 RecordingNetLogObserver net_log_observer_;
443 NetLogWithSource net_log_with_source_{
444 NetLogWithSource::Make(NetLogSourceType::NONE)};
445 TestJobFactory job_factory_;
446 MockHttpStreamRequestDelegate request_delegate_;
447 MockQuicContext quic_context_;
448 SpdySessionDependencies session_deps_;
449 std::unique_ptr<HttpNetworkSession> session_;
450 raw_ptr<HttpStreamFactory> factory_ = nullptr;
451 raw_ptr<HttpStreamFactory::JobController, AcrossTasksDanglingUntriaged>
452 job_controller_ = nullptr;
453 std::unique_ptr<HttpStreamRequest> request_;
454 std::unique_ptr<SequencedSocketData> tcp_data_;
455 std::unique_ptr<SequencedSocketData> tcp_data2_;
456 std::unique_ptr<MockQuicData> quic_data_;
457 std::unique_ptr<MockQuicData> quic_data2_;
458 MockCryptoClientStreamFactory crypto_client_stream_factory_;
459 QuicTestPacketMaker client_maker_{version_,
460 quic::QuicUtils::CreateRandomConnectionId(
461 quic_context_.random_generator()),
462 quic_context_.clock(),
463 kServerHostname,
464 quic::Perspective::IS_CLIENT,
465 false};
466
467 protected:
468 bool is_preconnect_ = false;
469 bool enable_ip_based_pooling_ = true;
470 bool enable_alternative_services_ = true;
471 bool delay_main_job_with_available_spdy_session_ = true;
472 bool should_check_data_consumed_ = true;
473
474 private:
475 bool dns_https_alpn_enabled_;
476 bool create_job_controller_ = true;
477
478 base::test::ScopedFeatureList feature_list_;
479 };
480
481 class HttpStreamFactoryJobControllerTest
482 : public HttpStreamFactoryJobControllerTestBase,
483 public ::testing::WithParamInterface<bool> {
484 protected:
HttpStreamFactoryJobControllerTest()485 HttpStreamFactoryJobControllerTest()
486 : HttpStreamFactoryJobControllerTestBase(GetParam()) {}
487 };
488
489 INSTANTIATE_TEST_SUITE_P(All,
490 HttpStreamFactoryJobControllerTest,
491 testing::Bool());
492
TEST_P(HttpStreamFactoryJobControllerTest,ProxyResolutionFailsSync)493 TEST_P(HttpStreamFactoryJobControllerTest, ProxyResolutionFailsSync) {
494 ProxyConfig proxy_config;
495 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
496 proxy_config.set_pac_mandatory(true);
497 session_deps_.proxy_resolution_service =
498 std::make_unique<ConfiguredProxyResolutionService>(
499
500 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
501 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
502 std::make_unique<FailingProxyResolverFactory>(), nullptr,
503 /*quick_check_enabled=*/true);
504 HttpRequestInfo request_info;
505 request_info.method = "GET";
506 request_info.url = GURL("http://www.google.com");
507
508 Initialize(request_info);
509
510 EXPECT_CALL(request_delegate_,
511 OnStreamFailed(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, _, _, _))
512 .Times(1);
513 request_ =
514 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
515 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
516
517 EXPECT_FALSE(job_controller_->main_job());
518 EXPECT_FALSE(job_controller_->alternative_job());
519
520 // Make sure calling GetLoadState() when before job creation does not crash.
521 // Regression test for crbug.com/723920.
522 EXPECT_EQ(LOAD_STATE_IDLE, job_controller_->GetLoadState());
523
524 base::RunLoop().RunUntilIdle();
525 request_.reset();
526 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
527 }
528
TEST_P(HttpStreamFactoryJobControllerTest,ProxyResolutionFailsAsync)529 TEST_P(HttpStreamFactoryJobControllerTest, ProxyResolutionFailsAsync) {
530 ProxyConfig proxy_config;
531 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
532 proxy_config.set_pac_mandatory(true);
533 auto proxy_resolver_factory =
534 std::make_unique<MockAsyncProxyResolverFactory>(false);
535 auto* proxy_resolver_factory_ptr = proxy_resolver_factory.get();
536 MockAsyncProxyResolver resolver;
537 session_deps_.proxy_resolution_service =
538 std::make_unique<ConfiguredProxyResolutionService>(
539
540 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
541 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
542 std::move(proxy_resolver_factory), nullptr,
543 /*quick_check_enabled=*/true);
544 HttpRequestInfo request_info;
545 request_info.method = "GET";
546 request_info.url = GURL("http://www.google.com");
547
548 Initialize(request_info);
549
550 request_ =
551 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
552 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
553
554 EXPECT_FALSE(job_controller_->main_job());
555 EXPECT_FALSE(job_controller_->alternative_job());
556
557 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL,
558 job_controller_->GetLoadState());
559
560 EXPECT_CALL(request_delegate_,
561 OnStreamFailed(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, _, _, _))
562 .Times(1);
563 proxy_resolver_factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(
564 ERR_FAILED, &resolver);
565 base::RunLoop().RunUntilIdle();
566 request_.reset();
567 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
568 }
569
TEST_P(HttpStreamFactoryJobControllerTest,NoSupportedProxies)570 TEST_P(HttpStreamFactoryJobControllerTest, NoSupportedProxies) {
571 session_deps_.proxy_resolution_service =
572 ConfiguredProxyResolutionService::CreateFixedFromProxyChainsForTest(
573 {ProxyChain::FromSchemeHostAndPort(ProxyServer::SCHEME_QUIC,
574 "myproxy.org", 443)},
575 TRAFFIC_ANNOTATION_FOR_TESTS);
576 session_deps_.enable_quic = false;
577 HttpRequestInfo request_info;
578 request_info.method = "GET";
579 request_info.url = GURL("http://www.google.com");
580
581 Initialize(request_info);
582
583 EXPECT_CALL(request_delegate_,
584 OnStreamFailed(ERR_NO_SUPPORTED_PROXIES, _, _, _))
585 .Times(1);
586 request_ =
587 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
588 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
589
590 EXPECT_FALSE(job_controller_->main_job());
591 EXPECT_FALSE(job_controller_->alternative_job());
592
593 base::RunLoop().RunUntilIdle();
594 request_.reset();
595 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
596 }
597
598 class JobControllerReconsiderProxyAfterErrorTest
599 : public HttpStreamFactoryJobControllerTestBase {
600 public:
JobControllerReconsiderProxyAfterErrorTest()601 JobControllerReconsiderProxyAfterErrorTest()
602 : HttpStreamFactoryJobControllerTestBase(false) {}
Initialize(std::unique_ptr<ProxyResolutionService> proxy_resolution_service,std::unique_ptr<ProxyDelegate> proxy_delegate=nullptr)603 void Initialize(
604 std::unique_ptr<ProxyResolutionService> proxy_resolution_service,
605 std::unique_ptr<ProxyDelegate> proxy_delegate = nullptr) {
606 session_deps_.proxy_delegate = std::move(proxy_delegate);
607 session_deps_.proxy_resolution_service =
608 std::move(proxy_resolution_service);
609 session_deps_.proxy_resolution_service->SetProxyDelegate(
610 session_deps_.proxy_delegate.get());
611 session_ = std::make_unique<HttpNetworkSession>(
612 SpdySessionDependencies::CreateSessionParams(&session_deps_),
613 SpdySessionDependencies::CreateSessionContext(&session_deps_));
614 factory_ = session_->http_stream_factory();
615 }
616
CreateJobController(const HttpRequestInfo & request_info)617 std::unique_ptr<HttpStreamRequest> CreateJobController(
618 const HttpRequestInfo& request_info) {
619 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
620 factory_, &request_delegate_, session_.get(), &default_job_factory_,
621 request_info, is_preconnect_, /*is_websocket=*/false,
622 enable_ip_based_pooling_, enable_alternative_services_,
623 delay_main_job_with_available_spdy_session_,
624 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
625 auto* job_controller_ptr = job_controller.get();
626 HttpStreamFactoryPeer::AddJobController(factory_,
627 std::move(job_controller));
628 return job_controller_ptr->Start(
629 &request_delegate_, nullptr, net_log_with_source_,
630 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
631 }
632
633 private:
634 // Use real Jobs so that Job::Resume() is not mocked out. When main job is
635 // resumed it will use mock socket data.
636 HttpStreamFactory::JobFactory default_job_factory_;
637 };
638
639 // Test proxy fallback logic in the case connecting through an HTTP proxy.
640 //
641 // TODO(eroman): The testing should be expanded to test cases where proxy
642 // fallback is NOT supposed to occur, and also vary across all of
643 // the proxy types.
TEST_F(JobControllerReconsiderProxyAfterErrorTest,ReconsiderProxyAfterErrorHttpProxy)644 TEST_F(JobControllerReconsiderProxyAfterErrorTest,
645 ReconsiderProxyAfterErrorHttpProxy) {
646 enum class ErrorPhase {
647 kHostResolution,
648 kTcpConnect,
649 kTunnelRead,
650 };
651
652 const struct {
653 ErrorPhase phase;
654 net::Error error;
655 } kRetriableErrors[] = {
656 // These largely correspond to the list of errors in
657 // CanFalloverToNextProxy() which can occur with an HTTP proxy.
658 //
659 // We omit `ERR_CONNECTION_CLOSED` because it is largely unreachable. The
660 // HTTP/1.1 parser maps it to `ERR_EMPTY_RESPONSE` or
661 // `ERR_RESPONSE_HEADERS_TRUNCATED` in most cases.
662 //
663 // TODO(davidben): Is omitting `ERR_EMPTY_RESPONSE` a bug in proxy error
664 // handling?
665 {ErrorPhase::kHostResolution, ERR_NAME_NOT_RESOLVED},
666 {ErrorPhase::kTcpConnect, ERR_ADDRESS_UNREACHABLE},
667 {ErrorPhase::kTcpConnect, ERR_CONNECTION_TIMED_OUT},
668 {ErrorPhase::kTcpConnect, ERR_CONNECTION_RESET},
669 {ErrorPhase::kTcpConnect, ERR_CONNECTION_ABORTED},
670 {ErrorPhase::kTcpConnect, ERR_CONNECTION_REFUSED},
671 {ErrorPhase::kTunnelRead, ERR_TIMED_OUT},
672 {ErrorPhase::kTunnelRead, ERR_SSL_PROTOCOL_ERROR},
673 };
674
675 for (GURL dest_url :
676 {GURL("http://www.example.com"), GURL("https://www.example.com")}) {
677 SCOPED_TRACE(dest_url);
678
679 for (const auto& mock_error : kRetriableErrors) {
680 SCOPED_TRACE(ErrorToString(mock_error.error));
681
682 CreateSessionDeps();
683
684 std::unique_ptr<ConfiguredProxyResolutionService>
685 proxy_resolution_service =
686 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
687 "PROXY badproxy:99; PROXY badfallbackproxy:98; DIRECT",
688 TRAFFIC_ANNOTATION_FOR_TESTS);
689 auto test_proxy_delegate = std::make_unique<TestProxyDelegate>();
690 test_proxy_delegate->set_extra_header_name("Foo");
691
692 // Before starting the test, verify that there are no proxies marked as
693 // bad.
694 ASSERT_TRUE(proxy_resolution_service->proxy_retry_info().empty());
695
696 constexpr char kBadProxyTunnelRequest[] =
697 "CONNECT www.example.com:443 HTTP/1.1\r\n"
698 "Host: www.example.com:443\r\n"
699 "Proxy-Connection: keep-alive\r\n"
700 "Foo: badproxy:99\r\n\r\n";
701 constexpr char kBadFallbackProxyTunnelRequest[] =
702 "CONNECT www.example.com:443 HTTP/1.1\r\n"
703 "Host: www.example.com:443\r\n"
704 "Proxy-Connection: keep-alive\r\n"
705 "Foo: badfallbackproxy:98\r\n\r\n";
706 const MockWrite kBadProxyTunnelWrites[] = {
707 {ASYNC, kBadProxyTunnelRequest}};
708 const MockWrite kBadFallbackProxyTunnelWrites[] = {
709 {ASYNC, kBadFallbackProxyTunnelRequest}};
710 std::vector<MockRead> reads;
711
712 // Generate identical errors for both the main proxy and the fallback
713 // proxy. No alternative job is created for either, so only need one data
714 // provider for each, when the request makes it to the socket layer.
715 std::unique_ptr<StaticSocketDataProvider> socket_data_proxy_main_job;
716 std::unique_ptr<StaticSocketDataProvider> socket_data_proxy_main_job2;
717 switch (mock_error.phase) {
718 case ErrorPhase::kHostResolution:
719 // Only ERR_NAME_NOT_RESOLVED can be returned by the mock host
720 // resolver.
721 DCHECK_EQ(ERR_NAME_NOT_RESOLVED, mock_error.error);
722 session_deps_.host_resolver->rules()->AddSimulatedFailure("badproxy");
723 session_deps_.host_resolver->rules()->AddSimulatedFailure(
724 "badfallbackproxy");
725 break;
726 case ErrorPhase::kTcpConnect:
727 socket_data_proxy_main_job =
728 std::make_unique<StaticSocketDataProvider>();
729 socket_data_proxy_main_job->set_connect_data(
730 MockConnect(ASYNC, mock_error.error));
731 socket_data_proxy_main_job2 =
732 std::make_unique<StaticSocketDataProvider>();
733 socket_data_proxy_main_job2->set_connect_data(
734 MockConnect(ASYNC, mock_error.error));
735 break;
736 case ErrorPhase::kTunnelRead:
737 // Tunnels aren't established for HTTP destinations.
738 if (dest_url.SchemeIs(url::kHttpScheme)) {
739 continue;
740 }
741 reads.emplace_back(ASYNC, mock_error.error);
742 socket_data_proxy_main_job =
743 std::make_unique<StaticSocketDataProvider>(reads,
744 kBadProxyTunnelWrites);
745 socket_data_proxy_main_job2 =
746 std::make_unique<StaticSocketDataProvider>(
747 reads, kBadFallbackProxyTunnelWrites);
748 break;
749 }
750
751 if (socket_data_proxy_main_job) {
752 session_deps_.socket_factory->AddSocketDataProvider(
753 socket_data_proxy_main_job.get());
754 session_deps_.socket_factory->AddSocketDataProvider(
755 socket_data_proxy_main_job2.get());
756 }
757
758 // After both proxies fail, the request should fall back to using DIRECT,
759 // and succeed.
760 SSLSocketDataProvider ssl_data_first_request(ASYNC, OK);
761 StaticSocketDataProvider socket_data_direct_first_request;
762 socket_data_direct_first_request.set_connect_data(MockConnect(ASYNC, OK));
763 session_deps_.socket_factory->AddSocketDataProvider(
764 &socket_data_direct_first_request);
765 // Only used in the HTTPS destination case, but harmless in the HTTP case.
766 session_deps_.socket_factory->AddSSLSocketDataProvider(
767 &ssl_data_first_request);
768
769 // Second request should use DIRECT, skipping the bad proxies, and
770 // succeed.
771 SSLSocketDataProvider ssl_data_second_request(ASYNC, OK);
772 StaticSocketDataProvider socket_data_direct_second_request;
773 socket_data_direct_second_request.set_connect_data(
774 MockConnect(ASYNC, OK));
775 session_deps_.socket_factory->AddSocketDataProvider(
776 &socket_data_direct_second_request);
777 // Only used in the HTTPS destination case, but harmless in the HTTP case.
778 session_deps_.socket_factory->AddSSLSocketDataProvider(
779 &ssl_data_second_request);
780
781 // Now request a stream. It should succeed using the DIRECT fallback proxy
782 // option.
783 HttpRequestInfo request_info;
784 request_info.method = "GET";
785 request_info.url = dest_url;
786 Initialize(std::move(proxy_resolution_service),
787 std::move(test_proxy_delegate));
788
789 // Start two requests. The first request should consume data from
790 // |socket_data_proxy_main_job| and |socket_data_direct_first_request|.
791 // The second request should consume data from
792 // |socket_data_direct_second_request|.
793
794 for (size_t i = 0; i < 2; ++i) {
795 ProxyInfo used_proxy_info;
796 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
797 .Times(1)
798 .WillOnce(::testing::SaveArg<0>(&used_proxy_info));
799
800 std::unique_ptr<HttpStreamRequest> request =
801 CreateJobController(request_info);
802 RunUntilIdle();
803
804 // Verify that request was fetched without proxy.
805 EXPECT_TRUE(used_proxy_info.is_direct());
806
807 // The proxies that failed should now be known to the proxy service as
808 // bad.
809 const ProxyRetryInfoMap& retry_info =
810 session_->proxy_resolution_service()->proxy_retry_info();
811 ASSERT_THAT(retry_info, SizeIs(2));
812 EXPECT_THAT(retry_info, Contains(Key(ProxyUriToProxyChain(
813 "badproxy:99", ProxyServer::SCHEME_HTTP))));
814 EXPECT_THAT(retry_info,
815 Contains(Key(ProxyUriToProxyChain(
816 "badfallbackproxy:98", ProxyServer::SCHEME_HTTP))));
817
818 // The idle socket should have been added back to the socket pool. Close
819 // it, so the next loop iteration creates a new socket instead of
820 // reusing the idle one.
821 auto* socket_pool = session_->GetSocketPool(
822 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct());
823 EXPECT_EQ(1, socket_pool->IdleSocketCount());
824 socket_pool->CloseIdleSockets("Close socket reason");
825 }
826 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
827 }
828 }
829 }
830
831 // Test proxy fallback logic in the case connecting through an HTTPS proxy.
TEST_F(JobControllerReconsiderProxyAfterErrorTest,ReconsiderProxyAfterErrorHttpsProxy)832 TEST_F(JobControllerReconsiderProxyAfterErrorTest,
833 ReconsiderProxyAfterErrorHttpsProxy) {
834 enum class ErrorPhase {
835 kHostResolution,
836 kTcpConnect,
837 kProxySslHandshake,
838 kTunnelRead,
839 };
840
841 const struct {
842 ErrorPhase phase;
843 net::Error error;
844 // Each test case simulates a connection attempt through a proxy that fails
845 // twice, followed by two connection attempts that succeed. For most cases,
846 // this is done by having a connection attempt to the first proxy fail,
847 // triggering fallback to a second proxy, which also fails, and then
848 // fallback to the final (DIRECT) proxy option. However, SslConnectJobs have
849 // their own try logic in certain cases. This value is true for those cases,
850 // in which case there are two connection attempts to the first proxy, and
851 // then the requests fall back to the second (DIRECT) proxy.
852 bool triggers_ssl_connect_job_retry_logic = false;
853 } kRetriableErrors[] = {
854 // These largely correspond to the list of errors in
855 // CanFalloverToNextProxy() which can occur with an HTTPS proxy.
856 //
857 // We omit `ERR_CONNECTION_CLOSED` because it is largely unreachable. The
858 // HTTP/1.1 parser maps it to `ERR_EMPTY_RESPONSE` or
859 // `ERR_RESPONSE_HEADERS_TRUNCATED` in most cases.
860 //
861 // TODO(davidben): Is omitting `ERR_EMPTY_RESPONSE` a bug in proxy error
862 // handling?
863 {ErrorPhase::kHostResolution, ERR_NAME_NOT_RESOLVED},
864 {ErrorPhase::kTcpConnect, ERR_ADDRESS_UNREACHABLE},
865 {ErrorPhase::kTcpConnect, ERR_CONNECTION_TIMED_OUT},
866 {ErrorPhase::kTcpConnect, ERR_CONNECTION_RESET},
867 {ErrorPhase::kTcpConnect, ERR_CONNECTION_ABORTED},
868 {ErrorPhase::kTcpConnect, ERR_CONNECTION_REFUSED},
869 {ErrorPhase::kProxySslHandshake, ERR_CERT_COMMON_NAME_INVALID},
870 {ErrorPhase::kProxySslHandshake, ERR_SSL_PROTOCOL_ERROR,
871 /*triggers_ssl_connect_job_retry_logic=*/true},
872 {ErrorPhase::kTunnelRead, ERR_TIMED_OUT},
873 {ErrorPhase::kTunnelRead, ERR_SSL_PROTOCOL_ERROR},
874 };
875
876 for (GURL dest_url :
877 {GURL("http://www.example.com"), GURL("https://www.example.com")}) {
878 SCOPED_TRACE(dest_url);
879
880 for (const auto& mock_error : kRetriableErrors) {
881 SCOPED_TRACE(ErrorToString(mock_error.error));
882
883 CreateSessionDeps();
884
885 std::unique_ptr<ConfiguredProxyResolutionService>
886 proxy_resolution_service =
887 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
888 "HTTPS badproxy:99; HTTPS badfallbackproxy:98; DIRECT",
889 TRAFFIC_ANNOTATION_FOR_TESTS);
890 if (mock_error.triggers_ssl_connect_job_retry_logic) {
891 proxy_resolution_service =
892 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
893 "HTTPS badproxy:99; DIRECT", TRAFFIC_ANNOTATION_FOR_TESTS);
894 }
895 auto test_proxy_delegate = std::make_unique<TestProxyDelegate>();
896 test_proxy_delegate->set_extra_header_name("Foo");
897
898 // Before starting the test, verify that there are no proxies marked as
899 // bad.
900 ASSERT_TRUE(proxy_resolution_service->proxy_retry_info().empty());
901
902 constexpr char kBadProxyTunnelRequest[] =
903 "CONNECT www.example.com:443 HTTP/1.1\r\n"
904 "Host: www.example.com:443\r\n"
905 "Proxy-Connection: keep-alive\r\n"
906 "Foo: https://badproxy:99\r\n\r\n";
907 constexpr char kBadFallbackProxyTunnelRequest[] =
908 "CONNECT www.example.com:443 HTTP/1.1\r\n"
909 "Host: www.example.com:443\r\n"
910 "Proxy-Connection: keep-alive\r\n"
911 "Foo: https://badfallbackproxy:98\r\n\r\n";
912 const MockWrite kBadProxyTunnelWrites[] = {
913 {ASYNC, kBadProxyTunnelRequest}};
914 const MockWrite kBadFallbackProxyTunnelWrites[] = {
915 {ASYNC, kBadFallbackProxyTunnelRequest}};
916 std::vector<MockRead> reads;
917
918 // Generate identical errors for both the main proxy and the fallback
919 // proxy. No alternative job is created for either, so only need one data
920 // provider for each, when the request makes it to the socket layer.
921 std::unique_ptr<StaticSocketDataProvider> socket_data_proxy_main_job;
922 std::unique_ptr<SSLSocketDataProvider> ssl_data_proxy_main_job;
923 std::unique_ptr<StaticSocketDataProvider> socket_data_proxy_main_job2;
924 std::unique_ptr<SSLSocketDataProvider> ssl_data_proxy_main_job2;
925 switch (mock_error.phase) {
926 case ErrorPhase::kHostResolution:
927 // Only ERR_NAME_NOT_RESOLVED can be returned by the mock host
928 // resolver.
929 DCHECK_EQ(ERR_NAME_NOT_RESOLVED, mock_error.error);
930 session_deps_.host_resolver->rules()->AddSimulatedFailure("badproxy");
931 session_deps_.host_resolver->rules()->AddSimulatedFailure(
932 "badfallbackproxy");
933 break;
934 case ErrorPhase::kTcpConnect:
935 socket_data_proxy_main_job =
936 std::make_unique<StaticSocketDataProvider>();
937 socket_data_proxy_main_job->set_connect_data(
938 MockConnect(ASYNC, mock_error.error));
939 socket_data_proxy_main_job2 =
940 std::make_unique<StaticSocketDataProvider>();
941 socket_data_proxy_main_job2->set_connect_data(
942 MockConnect(ASYNC, mock_error.error));
943 break;
944 case ErrorPhase::kProxySslHandshake:
945 socket_data_proxy_main_job =
946 std::make_unique<StaticSocketDataProvider>();
947 ssl_data_proxy_main_job =
948 std::make_unique<SSLSocketDataProvider>(ASYNC, mock_error.error);
949 socket_data_proxy_main_job2 =
950 std::make_unique<StaticSocketDataProvider>();
951 ssl_data_proxy_main_job2 =
952 std::make_unique<SSLSocketDataProvider>(ASYNC, mock_error.error);
953 break;
954 case ErrorPhase::kTunnelRead:
955 // Tunnels aren't established for HTTP destinations.
956 if (dest_url.SchemeIs(url::kHttpScheme)) {
957 continue;
958 }
959 reads.emplace_back(ASYNC, mock_error.error);
960 socket_data_proxy_main_job =
961 std::make_unique<StaticSocketDataProvider>(reads,
962 kBadProxyTunnelWrites);
963 ssl_data_proxy_main_job =
964 std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
965 socket_data_proxy_main_job2 =
966 std::make_unique<StaticSocketDataProvider>(
967 reads, mock_error.triggers_ssl_connect_job_retry_logic
968 ? kBadProxyTunnelWrites
969 : kBadFallbackProxyTunnelWrites);
970 ssl_data_proxy_main_job2 =
971 std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
972 break;
973 }
974
975 if (socket_data_proxy_main_job) {
976 session_deps_.socket_factory->AddSocketDataProvider(
977 socket_data_proxy_main_job.get());
978 session_deps_.socket_factory->AddSocketDataProvider(
979 socket_data_proxy_main_job2.get());
980 }
981 if (ssl_data_proxy_main_job) {
982 session_deps_.socket_factory->AddSSLSocketDataProvider(
983 ssl_data_proxy_main_job.get());
984 session_deps_.socket_factory->AddSSLSocketDataProvider(
985 ssl_data_proxy_main_job2.get());
986 }
987
988 // After both proxies fail, the request should fall back to using DIRECT,
989 // and succeed.
990 SSLSocketDataProvider ssl_data_first_request(ASYNC, OK);
991 StaticSocketDataProvider socket_data_direct_first_request;
992 socket_data_direct_first_request.set_connect_data(MockConnect(ASYNC, OK));
993 session_deps_.socket_factory->AddSocketDataProvider(
994 &socket_data_direct_first_request);
995 // Only used in the HTTPS destination case, but harmless in the HTTP case.
996 session_deps_.socket_factory->AddSSLSocketDataProvider(
997 &ssl_data_first_request);
998
999 // Second request should use DIRECT, skipping the bad proxies, and
1000 // succeed.
1001 SSLSocketDataProvider ssl_data_second_request(ASYNC, OK);
1002 StaticSocketDataProvider socket_data_direct_second_request;
1003 socket_data_direct_second_request.set_connect_data(
1004 MockConnect(ASYNC, OK));
1005 session_deps_.socket_factory->AddSocketDataProvider(
1006 &socket_data_direct_second_request);
1007 // Only used in the HTTPS destination case, but harmless in the HTTP case.
1008 session_deps_.socket_factory->AddSSLSocketDataProvider(
1009 &ssl_data_second_request);
1010
1011 // Now request a stream. It should succeed using the DIRECT fallback proxy
1012 // option.
1013 HttpRequestInfo request_info;
1014 request_info.method = "GET";
1015 request_info.url = dest_url;
1016
1017 Initialize(std::move(proxy_resolution_service),
1018 std::move(test_proxy_delegate));
1019
1020 // Start two requests. The first request should consume data from
1021 // |socket_data_proxy_main_job| and |socket_data_direct_first_request|.
1022 // The second request should consume data from
1023 // |socket_data_direct_second_request|.
1024
1025 for (size_t i = 0; i < 2; ++i) {
1026 ProxyInfo used_proxy_info;
1027 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
1028 .Times(1)
1029 .WillOnce(::testing::SaveArg<0>(&used_proxy_info));
1030
1031 std::unique_ptr<HttpStreamRequest> request =
1032 CreateJobController(request_info);
1033 RunUntilIdle();
1034
1035 // Verify that request was fetched without proxy.
1036 EXPECT_TRUE(used_proxy_info.is_direct());
1037
1038 // The proxies that failed should now be known to the proxy service as
1039 // bad.
1040 const ProxyRetryInfoMap& retry_info =
1041 session_->proxy_resolution_service()->proxy_retry_info();
1042 if (!mock_error.triggers_ssl_connect_job_retry_logic) {
1043 ASSERT_THAT(retry_info, SizeIs(2));
1044 EXPECT_THAT(retry_info,
1045 Contains(Key(ProxyUriToProxyChain(
1046 "https://badproxy:99", ProxyServer::SCHEME_HTTP))));
1047 EXPECT_THAT(
1048 retry_info,
1049 Contains(Key(ProxyUriToProxyChain("https://badfallbackproxy:98",
1050 ProxyServer::SCHEME_HTTP))));
1051 } else {
1052 ASSERT_THAT(retry_info, SizeIs(1));
1053 EXPECT_THAT(retry_info,
1054 Contains(Key(ProxyUriToProxyChain(
1055 "https://badproxy:99", ProxyServer::SCHEME_HTTP))));
1056 }
1057
1058 // The idle socket should have been added back to the socket pool. Close
1059 // it, so the next loop iteration creates a new socket instead of
1060 // reusing the idle one.
1061 auto* socket_pool = session_->GetSocketPool(
1062 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct());
1063 EXPECT_EQ(1, socket_pool->IdleSocketCount());
1064 socket_pool->CloseIdleSockets("Close socket reason");
1065 }
1066 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
1067 }
1068 }
1069 }
1070
1071 // Same as above but using a multi-proxy chain, with errors encountered by the
1072 // first proxy server in the chain.
TEST_F(JobControllerReconsiderProxyAfterErrorTest,ReconsiderProxyAfterFirstNestedProxyErrorHttps)1073 TEST_F(JobControllerReconsiderProxyAfterErrorTest,
1074 ReconsiderProxyAfterFirstNestedProxyErrorHttps) {
1075 enum class ErrorPhase {
1076 kHostResolution,
1077 kTcpConnect,
1078 kProxySslHandshake,
1079 kTunnelRead,
1080 };
1081
1082 const struct {
1083 ErrorPhase phase;
1084 net::Error error;
1085 // For a description of this field, see the corresponding struct member
1086 // comment in `ReconsiderProxyAfterErrorHttpsProxy`.
1087 bool triggers_ssl_connect_job_retry_logic = false;
1088 } kRetriableErrors[] = {
1089 // These largely correspond to the list of errors in
1090 // CanFalloverToNextProxy() which can occur with an HTTPS proxy.
1091 //
1092 // We omit `ERR_CONNECTION_CLOSED` because it is largely unreachable. The
1093 // HTTP/1.1 parser maps it to `ERR_EMPTY_RESPONSE` or
1094 // `ERR_RESPONSE_HEADERS_TRUNCATED` in most cases.
1095 //
1096 // TODO(davidben): Is omitting `ERR_EMPTY_RESPONSE` a bug in proxy error
1097 // handling?
1098 {ErrorPhase::kHostResolution, ERR_NAME_NOT_RESOLVED},
1099 {ErrorPhase::kTcpConnect, ERR_ADDRESS_UNREACHABLE},
1100 {ErrorPhase::kTcpConnect, ERR_CONNECTION_TIMED_OUT},
1101 {ErrorPhase::kTcpConnect, ERR_CONNECTION_RESET},
1102 {ErrorPhase::kTcpConnect, ERR_CONNECTION_ABORTED},
1103 {ErrorPhase::kTcpConnect, ERR_CONNECTION_REFUSED},
1104 {ErrorPhase::kProxySslHandshake, ERR_CERT_COMMON_NAME_INVALID},
1105 {ErrorPhase::kProxySslHandshake, ERR_SSL_PROTOCOL_ERROR,
1106 /*triggers_ssl_connect_job_retry_logic=*/true},
1107 {ErrorPhase::kTunnelRead, ERR_TIMED_OUT},
1108 {ErrorPhase::kTunnelRead, ERR_SSL_PROTOCOL_ERROR},
1109 };
1110
1111 const ProxyServer kGoodProxyServer{ProxyServer::SCHEME_HTTPS,
1112 HostPortPair("goodproxyserver", 100)};
1113 const ProxyServer kBadProxyServer1{ProxyServer::SCHEME_HTTPS,
1114 HostPortPair("badproxyserver", 99)};
1115 const ProxyServer kBadProxyServer2{
1116 ProxyServer::SCHEME_HTTPS, HostPortPair("badfallbackproxyserver", 98)};
1117 const ProxyChain kNestedProxyChain1{{kBadProxyServer1, kGoodProxyServer}};
1118 const ProxyChain kNestedProxyChain2{{kBadProxyServer2, kGoodProxyServer}};
1119
1120 for (GURL dest_url :
1121 {GURL("http://www.example.com"), GURL("https://www.example.com")}) {
1122 SCOPED_TRACE(dest_url);
1123
1124 for (const auto& mock_error : kRetriableErrors) {
1125 SCOPED_TRACE(ErrorToString(mock_error.error));
1126
1127 CreateSessionDeps();
1128
1129 ProxyList proxy_list;
1130 proxy_list.AddProxyChain(kNestedProxyChain1);
1131 proxy_list.AddProxyChain(kNestedProxyChain2);
1132 proxy_list.AddProxyChain(ProxyChain::Direct());
1133 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
1134
1135 std::unique_ptr<ConfiguredProxyResolutionService>
1136 proxy_resolution_service =
1137 ConfiguredProxyResolutionService::CreateFixedForTest(
1138 ProxyConfigWithAnnotation(proxy_config,
1139 TRAFFIC_ANNOTATION_FOR_TESTS));
1140
1141 if (mock_error.triggers_ssl_connect_job_retry_logic) {
1142 proxy_list.Clear();
1143 proxy_list.AddProxyChain(kNestedProxyChain1);
1144 proxy_list.AddProxyChain(ProxyChain::Direct());
1145 ProxyConfig proxy_config2 = ProxyConfig::CreateForTesting(proxy_list);
1146
1147 proxy_resolution_service =
1148 ConfiguredProxyResolutionService::CreateFixedForTest(
1149 ProxyConfigWithAnnotation(proxy_config2,
1150 TRAFFIC_ANNOTATION_FOR_TESTS));
1151 }
1152 auto test_proxy_delegate = std::make_unique<TestProxyDelegate>();
1153 test_proxy_delegate->set_extra_header_name("Foo");
1154
1155 // Before starting the test, verify that there are no proxies marked as
1156 // bad.
1157 ASSERT_TRUE(proxy_resolution_service->proxy_retry_info().empty());
1158
1159 constexpr char kBadProxyServer1TunnelRequest[] =
1160 "CONNECT goodproxyserver:100 HTTP/1.1\r\n"
1161 "Host: goodproxyserver:100\r\n"
1162 "Proxy-Connection: keep-alive\r\n"
1163 "Foo: https://badproxyserver:99\r\n\r\n";
1164 constexpr char kBadProxyServer2TunnelRequest[] =
1165 "CONNECT goodproxyserver:100 HTTP/1.1\r\n"
1166 "Host: goodproxyserver:100\r\n"
1167 "Proxy-Connection: keep-alive\r\n"
1168 "Foo: https://badfallbackproxyserver:98\r\n\r\n";
1169 const MockWrite kBadProxyServer1TunnelWrites[] = {
1170 MockWrite(ASYNC, 0, kBadProxyServer1TunnelRequest)};
1171 const MockWrite kBadProxyServer2TunnelWrites[] = {
1172 MockWrite(ASYNC, 0, kBadProxyServer2TunnelRequest)};
1173 std::vector<MockRead> reads;
1174
1175 // Generate identical errors for the first proxy server in both the main
1176 // proxy chain and the fallback proxy chain. No alternative job is created
1177 // for either, so only need one data provider for each, when the request
1178 // makes it to the socket layer.
1179 std::unique_ptr<SequencedSocketData> socket_data_proxy_main_job;
1180 std::unique_ptr<SSLSocketDataProvider> ssl_data_proxy_main_job;
1181 std::unique_ptr<SequencedSocketData> socket_data_proxy_main_job2;
1182 std::unique_ptr<SSLSocketDataProvider> ssl_data_proxy_main_job2;
1183 switch (mock_error.phase) {
1184 case ErrorPhase::kHostResolution:
1185 // Only ERR_NAME_NOT_RESOLVED can be returned by the mock host
1186 // resolver.
1187 DCHECK_EQ(ERR_NAME_NOT_RESOLVED, mock_error.error);
1188 session_deps_.host_resolver->rules()->AddSimulatedFailure(
1189 "badproxyserver");
1190 session_deps_.host_resolver->rules()->AddSimulatedFailure(
1191 "badfallbackproxyserver");
1192 break;
1193 case ErrorPhase::kTcpConnect:
1194 socket_data_proxy_main_job = std::make_unique<SequencedSocketData>();
1195 socket_data_proxy_main_job->set_connect_data(
1196 MockConnect(ASYNC, mock_error.error));
1197 socket_data_proxy_main_job2 = std::make_unique<SequencedSocketData>();
1198 socket_data_proxy_main_job2->set_connect_data(
1199 MockConnect(ASYNC, mock_error.error));
1200 break;
1201 case ErrorPhase::kProxySslHandshake:
1202 socket_data_proxy_main_job = std::make_unique<SequencedSocketData>();
1203 ssl_data_proxy_main_job =
1204 std::make_unique<SSLSocketDataProvider>(ASYNC, mock_error.error);
1205 socket_data_proxy_main_job2 = std::make_unique<SequencedSocketData>();
1206 ssl_data_proxy_main_job2 =
1207 std::make_unique<SSLSocketDataProvider>(ASYNC, mock_error.error);
1208 break;
1209 case ErrorPhase::kTunnelRead:
1210 // Note: Unlike for single-proxy chains, tunnels are established for
1211 // HTTP destinations when multi-proxy chains are in use, so simulate
1212 // tunnel read failures in all cases.
1213 reads.emplace_back(MockRead(ASYNC, mock_error.error, 1));
1214 socket_data_proxy_main_job = std::make_unique<SequencedSocketData>(
1215 reads, kBadProxyServer1TunnelWrites);
1216 ssl_data_proxy_main_job =
1217 std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
1218 socket_data_proxy_main_job2 = std::make_unique<SequencedSocketData>(
1219 reads, kBadProxyServer2TunnelWrites);
1220 ssl_data_proxy_main_job2 =
1221 std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
1222 break;
1223 }
1224
1225 if (socket_data_proxy_main_job) {
1226 session_deps_.socket_factory->AddSocketDataProvider(
1227 socket_data_proxy_main_job.get());
1228 session_deps_.socket_factory->AddSocketDataProvider(
1229 socket_data_proxy_main_job2.get());
1230 }
1231 if (ssl_data_proxy_main_job) {
1232 session_deps_.socket_factory->AddSSLSocketDataProvider(
1233 ssl_data_proxy_main_job.get());
1234 session_deps_.socket_factory->AddSSLSocketDataProvider(
1235 ssl_data_proxy_main_job2.get());
1236 }
1237
1238 // After both proxy chains fail, the request should fall back to using
1239 // DIRECT, and succeed.
1240 SSLSocketDataProvider ssl_data_first_request(ASYNC, OK);
1241 StaticSocketDataProvider socket_data_direct_first_request;
1242 socket_data_direct_first_request.set_connect_data(MockConnect(ASYNC, OK));
1243 session_deps_.socket_factory->AddSocketDataProvider(
1244 &socket_data_direct_first_request);
1245 // Only used in the HTTPS destination case, but harmless in the HTTP case.
1246 session_deps_.socket_factory->AddSSLSocketDataProvider(
1247 &ssl_data_first_request);
1248
1249 // Second request should use DIRECT, skipping the bad proxies, and
1250 // succeed.
1251 SSLSocketDataProvider ssl_data_second_request(ASYNC, OK);
1252 StaticSocketDataProvider socket_data_direct_second_request;
1253 socket_data_direct_second_request.set_connect_data(
1254 MockConnect(ASYNC, OK));
1255 session_deps_.socket_factory->AddSocketDataProvider(
1256 &socket_data_direct_second_request);
1257 session_deps_.socket_factory->AddSSLSocketDataProvider(
1258 &ssl_data_second_request);
1259
1260 // Now request a stream. It should succeed using the DIRECT fallback proxy
1261 // option.
1262 HttpRequestInfo request_info;
1263 request_info.method = "GET";
1264 request_info.url = dest_url;
1265
1266 Initialize(std::move(proxy_resolution_service),
1267 std::move(test_proxy_delegate));
1268
1269 // Start two requests. The first request should consume data from
1270 // `socket_data_proxy_main_job` and `socket_data_direct_first_request`.
1271 // The second request should consume data from
1272 // `socket_data_direct_second_request`.
1273
1274 for (size_t i = 0; i < 2; ++i) {
1275 ProxyInfo used_proxy_info;
1276 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
1277 .Times(1)
1278 .WillOnce(::testing::SaveArg<0>(&used_proxy_info));
1279
1280 std::unique_ptr<HttpStreamRequest> request =
1281 CreateJobController(request_info);
1282 RunUntilIdle();
1283
1284 // Verify that request was fetched without proxy.
1285 EXPECT_TRUE(used_proxy_info.is_direct());
1286
1287 // The proxies that failed should now be known to the proxy service as
1288 // bad.
1289 const ProxyRetryInfoMap& retry_info =
1290 session_->proxy_resolution_service()->proxy_retry_info();
1291 if (!mock_error.triggers_ssl_connect_job_retry_logic) {
1292 ASSERT_THAT(retry_info, SizeIs(2));
1293 EXPECT_THAT(retry_info, Contains(Key(kNestedProxyChain1)));
1294 EXPECT_THAT(retry_info, Contains(Key(kNestedProxyChain2)));
1295 } else {
1296 ASSERT_THAT(retry_info, SizeIs(1));
1297 EXPECT_THAT(retry_info, Contains(Key(kNestedProxyChain1)));
1298 }
1299
1300 // The idle socket should have been added back to the socket pool. Close
1301 // it, so the next loop iteration creates a new socket instead of
1302 // reusing the idle one.
1303 auto* socket_pool = session_->GetSocketPool(
1304 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct());
1305 EXPECT_EQ(1, socket_pool->IdleSocketCount());
1306 socket_pool->CloseIdleSockets("Close socket reason");
1307 }
1308 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
1309 }
1310 }
1311 }
1312
1313 // Same as above but using a multi-proxy chain, with errors encountered by the
1314 // second proxy server in the chain.
TEST_F(JobControllerReconsiderProxyAfterErrorTest,ReconsiderProxyAfterSecondNestedProxyErrorHttps)1315 TEST_F(JobControllerReconsiderProxyAfterErrorTest,
1316 ReconsiderProxyAfterSecondNestedProxyErrorHttps) {
1317 enum class ErrorPhase {
1318 // Note: Skip the kHostResolution and kTcpConnect cases for this test since
1319 // those only make sense for connections to the first proxy server.
1320 kProxySslHandshake,
1321 kTunnelRead,
1322 };
1323
1324 const struct {
1325 ErrorPhase phase;
1326 net::Error error;
1327 // For a description of this field, see the corresponding struct member
1328 // comment in `ReconsiderProxyAfterErrorHttpsProxy`.
1329 bool triggers_ssl_connect_job_retry_logic = false;
1330 } kRetriableErrors[] = {
1331 // These largely correspond to the list of errors in
1332 // CanFalloverToNextProxy() which can occur with an HTTPS proxy.
1333 //
1334 // We omit `ERR_CONNECTION_CLOSED` because it is largely unreachable. The
1335 // HTTP/1.1 parser maps it to `ERR_EMPTY_RESPONSE` or
1336 // `ERR_RESPONSE_HEADERS_TRUNCATED` in most cases.
1337 //
1338 // TODO(davidben): Is omitting `ERR_EMPTY_RESPONSE` a bug in proxy error
1339 // handling?
1340 {ErrorPhase::kProxySslHandshake, ERR_CERT_COMMON_NAME_INVALID},
1341 {ErrorPhase::kProxySslHandshake, ERR_SSL_PROTOCOL_ERROR,
1342 /*triggers_ssl_connect_job_retry_logic=*/true},
1343 {ErrorPhase::kTunnelRead, ERR_TIMED_OUT},
1344 {ErrorPhase::kTunnelRead, ERR_SSL_PROTOCOL_ERROR},
1345 };
1346
1347 const ProxyServer kGoodProxyServer{ProxyServer::SCHEME_HTTPS,
1348 HostPortPair("goodproxyserver", 100)};
1349 const ProxyServer kBadProxyServer1{ProxyServer::SCHEME_HTTPS,
1350 HostPortPair("badproxyserver", 99)};
1351 const ProxyServer kBadProxyServer2{
1352 ProxyServer::SCHEME_HTTPS, HostPortPair("badfallbackproxyserver", 98)};
1353 const ProxyChain kNestedProxyChain1{{kGoodProxyServer, kBadProxyServer1}};
1354 const ProxyChain kNestedProxyChain2{{kGoodProxyServer, kBadProxyServer2}};
1355
1356 for (GURL dest_url :
1357 {GURL("http://www.example.com"), GURL("https://www.example.com")}) {
1358 SCOPED_TRACE(dest_url);
1359
1360 for (const auto& mock_error : kRetriableErrors) {
1361 SCOPED_TRACE(ErrorToString(mock_error.error));
1362
1363 CreateSessionDeps();
1364
1365 ProxyList proxy_list;
1366 proxy_list.AddProxyChain(kNestedProxyChain1);
1367 proxy_list.AddProxyChain(kNestedProxyChain2);
1368 proxy_list.AddProxyChain(ProxyChain::Direct());
1369 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
1370
1371 std::unique_ptr<ConfiguredProxyResolutionService>
1372 proxy_resolution_service =
1373 ConfiguredProxyResolutionService::CreateFixedForTest(
1374 ProxyConfigWithAnnotation(proxy_config,
1375 TRAFFIC_ANNOTATION_FOR_TESTS));
1376
1377 if (mock_error.triggers_ssl_connect_job_retry_logic) {
1378 proxy_list.Clear();
1379 proxy_list.AddProxyChain(kNestedProxyChain1);
1380 proxy_list.AddProxyChain(ProxyChain::Direct());
1381 ProxyConfig proxy_config2 = ProxyConfig::CreateForTesting(proxy_list);
1382
1383 proxy_resolution_service =
1384 ConfiguredProxyResolutionService::CreateFixedForTest(
1385 ProxyConfigWithAnnotation(proxy_config2,
1386 TRAFFIC_ANNOTATION_FOR_TESTS));
1387 }
1388 auto test_proxy_delegate = std::make_unique<TestProxyDelegate>();
1389 test_proxy_delegate->set_extra_header_name("Foo");
1390
1391 // Before starting the test, verify that there are no proxies marked as
1392 // bad.
1393 ASSERT_TRUE(proxy_resolution_service->proxy_retry_info().empty());
1394
1395 constexpr char kBadProxyServer1TunnelRequest[] =
1396 "CONNECT badproxyserver:99 HTTP/1.1\r\n"
1397 "Host: badproxyserver:99\r\n"
1398 "Proxy-Connection: keep-alive\r\n"
1399 "Foo: https://goodproxyserver:100\r\n\r\n";
1400 constexpr char kBadProxyServer2TunnelRequest[] =
1401 "CONNECT badfallbackproxyserver:98 HTTP/1.1\r\n"
1402 "Host: badfallbackproxyserver:98\r\n"
1403 "Proxy-Connection: keep-alive\r\n"
1404 "Foo: https://goodproxyserver:100\r\n\r\n";
1405 const std::string kBadProxyServer1EndpointTunnelRequest =
1406 base::StringPrintf(
1407 "CONNECT %s HTTP/1.1\r\n"
1408 "Host: %s\r\n"
1409 "Proxy-Connection: keep-alive\r\n"
1410 "Foo: https://badproxyserver:99\r\n\r\n",
1411 HostPortPair::FromURL(dest_url).ToString().c_str(),
1412 HostPortPair::FromURL(dest_url).ToString().c_str());
1413 const std::string kBadProxyServer2EndpointTunnelRequest =
1414 base::StringPrintf(
1415 "CONNECT %s HTTP/1.1\r\n"
1416 "Host: %s\r\n"
1417 "Proxy-Connection: keep-alive\r\n"
1418 "Foo: https://badfallbackproxyserver:98\r\n\r\n",
1419 HostPortPair::FromURL(dest_url).ToString().c_str(),
1420 HostPortPair::FromURL(dest_url).ToString().c_str());
1421 const MockWrite kNestedProxyChain1TunnelWrites[] = {
1422 {ASYNC, kBadProxyServer1TunnelRequest},
1423 {ASYNC, kBadProxyServer1EndpointTunnelRequest.c_str()}};
1424 const MockWrite kNestedProxyChain2TunnelWrites[] = {
1425 {ASYNC, kBadProxyServer2TunnelRequest},
1426 {ASYNC, kBadProxyServer2EndpointTunnelRequest.c_str()}};
1427
1428 std::vector<MockRead> reads = {
1429 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
1430 };
1431
1432 // Generate identical errors for the second proxy server in both the main
1433 // proxy chain and the fallback proxy chain. No alternative job is created
1434 // for either, so only need one data provider for each, when the request
1435 // makes it to the socket layer.
1436 std::unique_ptr<StaticSocketDataProvider> socket_data_proxy_main_job;
1437 std::unique_ptr<SSLSocketDataProvider> ssl_data_proxy_main_job_server1;
1438 std::unique_ptr<SSLSocketDataProvider> ssl_data_proxy_main_job_server2;
1439 std::unique_ptr<StaticSocketDataProvider> socket_data_proxy_main_job2;
1440 std::unique_ptr<SSLSocketDataProvider> ssl_data_proxy_main_job2_server1;
1441 std::unique_ptr<SSLSocketDataProvider> ssl_data_proxy_main_job2_server2;
1442
1443 ssl_data_proxy_main_job_server1 =
1444 std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
1445 ssl_data_proxy_main_job2_server1 =
1446 std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
1447
1448 switch (mock_error.phase) {
1449 case ErrorPhase::kProxySslHandshake:
1450 ssl_data_proxy_main_job_server2 =
1451 std::make_unique<SSLSocketDataProvider>(ASYNC, mock_error.error);
1452 ssl_data_proxy_main_job2_server2 =
1453 std::make_unique<SSLSocketDataProvider>(ASYNC, mock_error.error);
1454 break;
1455 case ErrorPhase::kTunnelRead:
1456 // Note: Unlike for single-proxy chains, tunnels are established for
1457 // HTTP destinations when multi-proxy chains are in use, so simulate
1458 // tunnel read failures in all cases.
1459 reads.emplace_back(ASYNC, mock_error.error);
1460 ssl_data_proxy_main_job_server2 =
1461 std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
1462 ssl_data_proxy_main_job2_server2 =
1463 std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
1464 break;
1465 }
1466 socket_data_proxy_main_job = std::make_unique<StaticSocketDataProvider>(
1467 reads, kNestedProxyChain1TunnelWrites);
1468 socket_data_proxy_main_job2 = std::make_unique<StaticSocketDataProvider>(
1469 reads, mock_error.triggers_ssl_connect_job_retry_logic
1470 ? kNestedProxyChain1TunnelWrites
1471 : kNestedProxyChain2TunnelWrites);
1472
1473 session_deps_.socket_factory->AddSocketDataProvider(
1474 socket_data_proxy_main_job.get());
1475 session_deps_.socket_factory->AddSSLSocketDataProvider(
1476 ssl_data_proxy_main_job_server1.get());
1477 session_deps_.socket_factory->AddSSLSocketDataProvider(
1478 ssl_data_proxy_main_job_server2.get());
1479
1480 session_deps_.socket_factory->AddSocketDataProvider(
1481 socket_data_proxy_main_job2.get());
1482 session_deps_.socket_factory->AddSSLSocketDataProvider(
1483 ssl_data_proxy_main_job2_server1.get());
1484 session_deps_.socket_factory->AddSSLSocketDataProvider(
1485 ssl_data_proxy_main_job2_server2.get());
1486
1487 // After both proxy chains fail, the request should fall back to using
1488 // DIRECT, and succeed.
1489 SSLSocketDataProvider ssl_data_first_request(ASYNC, OK);
1490 StaticSocketDataProvider socket_data_direct_first_request;
1491 socket_data_direct_first_request.set_connect_data(MockConnect(ASYNC, OK));
1492 session_deps_.socket_factory->AddSocketDataProvider(
1493 &socket_data_direct_first_request);
1494 session_deps_.socket_factory->AddSSLSocketDataProvider(
1495 &ssl_data_first_request);
1496
1497 // Second request should use DIRECT, skipping the bad proxies, and
1498 // succeed.
1499 SSLSocketDataProvider ssl_data_second_request(ASYNC, OK);
1500 StaticSocketDataProvider socket_data_direct_second_request;
1501 socket_data_direct_second_request.set_connect_data(
1502 MockConnect(ASYNC, OK));
1503 session_deps_.socket_factory->AddSocketDataProvider(
1504 &socket_data_direct_second_request);
1505 // Only used in the HTTPS destination case, but harmless in the HTTP case.
1506 session_deps_.socket_factory->AddSSLSocketDataProvider(
1507 &ssl_data_second_request);
1508
1509 // Now request a stream. It should succeed using the DIRECT fallback proxy
1510 // option.
1511 HttpRequestInfo request_info;
1512 request_info.method = "GET";
1513 request_info.url = dest_url;
1514
1515 Initialize(std::move(proxy_resolution_service),
1516 std::move(test_proxy_delegate));
1517
1518 // Start two requests. The first request should consume data from
1519 // `socket_data_proxy_main_job` and `socket_data_direct_first_request`.
1520 // The second request should consume data from
1521 // `socket_data_direct_second_request`.
1522
1523 for (size_t i = 0; i < 2; ++i) {
1524 ProxyInfo used_proxy_info;
1525 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
1526 .Times(1)
1527 .WillOnce(::testing::SaveArg<0>(&used_proxy_info));
1528
1529 std::unique_ptr<HttpStreamRequest> request =
1530 CreateJobController(request_info);
1531 RunUntilIdle();
1532
1533 // Verify that request was fetched without proxy.
1534 EXPECT_TRUE(used_proxy_info.is_direct());
1535
1536 // The proxies that failed should now be known to the proxy service as
1537 // bad.
1538 const ProxyRetryInfoMap& retry_info =
1539 session_->proxy_resolution_service()->proxy_retry_info();
1540 if (!mock_error.triggers_ssl_connect_job_retry_logic) {
1541 ASSERT_THAT(retry_info, SizeIs(2));
1542 EXPECT_THAT(retry_info, Contains(Key(kNestedProxyChain1)));
1543 EXPECT_THAT(retry_info, Contains(Key(kNestedProxyChain2)));
1544 } else {
1545 ASSERT_THAT(retry_info, SizeIs(1));
1546 EXPECT_THAT(retry_info, Contains(Key(kNestedProxyChain1)));
1547 }
1548
1549 // The idle socket should have been added back to the socket pool. Close
1550 // it, so the next loop iteration creates a new socket instead of
1551 // reusing the idle one.
1552 auto* socket_pool = session_->GetSocketPool(
1553 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct());
1554 EXPECT_EQ(1, socket_pool->IdleSocketCount());
1555 socket_pool->CloseIdleSockets("Close socket reason");
1556 }
1557 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
1558 }
1559 }
1560 }
1561
1562 // Test proxy fallback logic for an IP Protection request.
TEST_F(JobControllerReconsiderProxyAfterErrorTest,ReconsiderProxyForIpProtection)1563 TEST_F(JobControllerReconsiderProxyAfterErrorTest,
1564 ReconsiderProxyForIpProtection) {
1565 GURL dest_url = GURL("https://www.example.com");
1566
1567 CreateSessionDeps();
1568
1569 std::unique_ptr<ConfiguredProxyResolutionService> proxy_resolution_service =
1570 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
1571 "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
1572 auto test_proxy_delegate =
1573 std::make_unique<TestProxyDelegateForIpProtection>();
1574
1575 // Before starting the test, verify that there are no proxies marked as
1576 // bad.
1577 ASSERT_TRUE(proxy_resolution_service->proxy_retry_info().empty());
1578
1579 constexpr char kTunnelRequest[] =
1580 "CONNECT www.example.com:443 HTTP/1.1\r\n"
1581 "Host: www.example.com:443\r\n"
1582 "Proxy-Connection: keep-alive\r\n"
1583 "Authorization: https://ip-pro:443\r\n\r\n";
1584 const MockWrite kTunnelWrites[] = {{ASYNC, kTunnelRequest}};
1585 std::vector<MockRead> reads;
1586
1587 // Generate errors for the first proxy server.
1588 std::unique_ptr<StaticSocketDataProvider> socket_data_proxy_main_job;
1589 std::unique_ptr<SSLSocketDataProvider> ssl_data_proxy_main_job;
1590 reads.emplace_back(ASYNC, ERR_TUNNEL_CONNECTION_FAILED);
1591 socket_data_proxy_main_job =
1592 std::make_unique<StaticSocketDataProvider>(reads, kTunnelWrites);
1593 ssl_data_proxy_main_job = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
1594
1595 session_deps_.socket_factory->AddSocketDataProvider(
1596 socket_data_proxy_main_job.get());
1597 session_deps_.socket_factory->AddSSLSocketDataProvider(
1598 ssl_data_proxy_main_job.get());
1599
1600 // After proxying fails, the request should fall back to using DIRECT, and
1601 // succeed.
1602 SSLSocketDataProvider ssl_data_first_request(ASYNC, OK);
1603 StaticSocketDataProvider socket_data_direct_first_request;
1604 socket_data_direct_first_request.set_connect_data(MockConnect(ASYNC, OK));
1605 session_deps_.socket_factory->AddSocketDataProvider(
1606 &socket_data_direct_first_request);
1607 session_deps_.socket_factory->AddSSLSocketDataProvider(
1608 &ssl_data_first_request);
1609
1610 HttpRequestInfo request_info;
1611 request_info.method = "GET";
1612 request_info.url = dest_url;
1613
1614 Initialize(std::move(proxy_resolution_service),
1615 std::move(test_proxy_delegate));
1616
1617 ProxyInfo used_proxy_info;
1618 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
1619 .Times(1)
1620 .WillOnce(::testing::SaveArg<0>(&used_proxy_info));
1621
1622 std::unique_ptr<HttpStreamRequest> request =
1623 CreateJobController(request_info);
1624 RunUntilIdle();
1625
1626 // Verify that request was fetched without proxy.
1627 EXPECT_TRUE(used_proxy_info.is_direct());
1628 }
1629
1630 // Test proxy fallback logic in the case connecting through socks5 proxy.
TEST_F(JobControllerReconsiderProxyAfterErrorTest,ReconsiderProxyAfterErrorSocks5Proxy)1631 TEST_F(JobControllerReconsiderProxyAfterErrorTest,
1632 ReconsiderProxyAfterErrorSocks5Proxy) {
1633 enum class ErrorPhase {
1634 kHostResolution,
1635 kTcpConnect,
1636 kTunnelRead,
1637 };
1638
1639 const struct {
1640 ErrorPhase phase;
1641 net::Error error;
1642 } kRetriableErrors[] = {
1643 // These largely correspond to the list of errors in
1644 // CanFalloverToNextProxy() which can occur with an HTTPS proxy.
1645 //
1646 // Unlike HTTP/HTTPS proxies, SOCKS proxies are retried in response to
1647 // `ERR_CONNECTION_CLOSED`.
1648 {ErrorPhase::kHostResolution, ERR_NAME_NOT_RESOLVED},
1649 {ErrorPhase::kTcpConnect, ERR_ADDRESS_UNREACHABLE},
1650 {ErrorPhase::kTcpConnect, ERR_CONNECTION_TIMED_OUT},
1651 {ErrorPhase::kTcpConnect, ERR_CONNECTION_RESET},
1652 {ErrorPhase::kTcpConnect, ERR_CONNECTION_ABORTED},
1653 {ErrorPhase::kTcpConnect, ERR_CONNECTION_REFUSED},
1654 {ErrorPhase::kTunnelRead, ERR_TIMED_OUT},
1655 {ErrorPhase::kTunnelRead, ERR_CONNECTION_CLOSED},
1656 };
1657
1658 // "host" on port 80 matches the kSOCK5GreetRequest.
1659 const GURL kDestUrl = GURL("http://host:80/");
1660
1661 for (const auto& mock_error : kRetriableErrors) {
1662 SCOPED_TRACE(ErrorToString(mock_error.error));
1663
1664 CreateSessionDeps();
1665
1666 std::unique_ptr<ConfiguredProxyResolutionService> proxy_resolution_service =
1667 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
1668 "SOCKS5 badproxy:99; SOCKS5 badfallbackproxy:98; DIRECT",
1669 TRAFFIC_ANNOTATION_FOR_TESTS);
1670 auto test_proxy_delegate = std::make_unique<TestProxyDelegate>();
1671
1672 // Before starting the test, verify that there are no proxies marked as bad.
1673 ASSERT_TRUE(proxy_resolution_service->proxy_retry_info().empty());
1674 const MockWrite kTunnelWrites[] = {
1675 {ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength}};
1676 std::vector<MockRead> reads;
1677
1678 // Generate identical errors for both the main proxy and the fallback proxy.
1679 // No alternative job is created for either, so only need one data provider
1680 // for each, when the request makes it to the socket layer.
1681 std::unique_ptr<StaticSocketDataProvider> socket_data_proxy_main_job;
1682 std::unique_ptr<StaticSocketDataProvider> socket_data_proxy_main_job2;
1683 switch (mock_error.phase) {
1684 case ErrorPhase::kHostResolution:
1685 // Only ERR_NAME_NOT_RESOLVED can be returned by the mock host resolver.
1686 DCHECK_EQ(ERR_NAME_NOT_RESOLVED, mock_error.error);
1687 session_deps_.host_resolver->rules()->AddSimulatedFailure("badproxy");
1688 session_deps_.host_resolver->rules()->AddSimulatedFailure(
1689 "badfallbackproxy");
1690 break;
1691 case ErrorPhase::kTcpConnect:
1692 socket_data_proxy_main_job =
1693 std::make_unique<StaticSocketDataProvider>();
1694 socket_data_proxy_main_job->set_connect_data(
1695 MockConnect(ASYNC, mock_error.error));
1696 socket_data_proxy_main_job2 =
1697 std::make_unique<StaticSocketDataProvider>();
1698 socket_data_proxy_main_job2->set_connect_data(
1699 MockConnect(ASYNC, mock_error.error));
1700 break;
1701 case ErrorPhase::kTunnelRead:
1702 reads.emplace_back(ASYNC, mock_error.error);
1703 socket_data_proxy_main_job =
1704 std::make_unique<StaticSocketDataProvider>(reads, kTunnelWrites);
1705 socket_data_proxy_main_job2 =
1706 std::make_unique<StaticSocketDataProvider>(reads, kTunnelWrites);
1707 break;
1708 }
1709
1710 if (socket_data_proxy_main_job) {
1711 session_deps_.socket_factory->AddSocketDataProvider(
1712 socket_data_proxy_main_job.get());
1713 session_deps_.socket_factory->AddSocketDataProvider(
1714 socket_data_proxy_main_job2.get());
1715 }
1716
1717 // After both proxies fail, the request should fall back to using DIRECT,
1718 // and succeed.
1719 StaticSocketDataProvider socket_data_direct_first_request;
1720 socket_data_direct_first_request.set_connect_data(MockConnect(ASYNC, OK));
1721 session_deps_.socket_factory->AddSocketDataProvider(
1722 &socket_data_direct_first_request);
1723
1724 // Second request should use DIRECT, skipping the bad proxies, and succeed.
1725 StaticSocketDataProvider socket_data_direct_second_request;
1726 socket_data_direct_second_request.set_connect_data(MockConnect(ASYNC, OK));
1727 session_deps_.socket_factory->AddSocketDataProvider(
1728 &socket_data_direct_second_request);
1729
1730 // Now request a stream. It should succeed using the DIRECT fallback proxy
1731 // option.
1732 HttpRequestInfo request_info;
1733 request_info.method = "GET";
1734 request_info.url = kDestUrl;
1735
1736 Initialize(std::move(proxy_resolution_service),
1737 std::move(test_proxy_delegate));
1738
1739 // Start two requests. The first request should consume data from
1740 // |socket_data_proxy_main_job| and |socket_data_direct_first_request|. The
1741 // second request should consume data from
1742 // |socket_data_direct_second_request|.
1743
1744 for (size_t i = 0; i < 2; ++i) {
1745 ProxyInfo used_proxy_info;
1746 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
1747 .Times(1)
1748 .WillOnce(::testing::SaveArg<0>(&used_proxy_info));
1749
1750 std::unique_ptr<HttpStreamRequest> request =
1751 CreateJobController(request_info);
1752 RunUntilIdle();
1753
1754 // Verify that request was fetched without proxy.
1755 EXPECT_TRUE(used_proxy_info.is_direct());
1756
1757 // The proxies that failed should now be known to the proxy service as
1758 // bad.
1759 const ProxyRetryInfoMap& retry_info =
1760 session_->proxy_resolution_service()->proxy_retry_info();
1761 ASSERT_THAT(retry_info, SizeIs(2));
1762 EXPECT_THAT(retry_info,
1763 Contains(Key(ProxyUriToProxyChain(
1764 "socks5://badproxy:99", ProxyServer::SCHEME_SOCKS5))));
1765 EXPECT_THAT(
1766 retry_info,
1767 Contains(Key(ProxyUriToProxyChain("socks5://badfallbackproxy:98",
1768 ProxyServer::SCHEME_SOCKS5))));
1769
1770 // The idle socket should have been added back to the socket pool. Close
1771 // it, so the next loop iteration creates a new socket instead of reusing
1772 // the idle one.
1773 auto* socket_pool = session_->GetSocketPool(
1774 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct());
1775 EXPECT_EQ(1, socket_pool->IdleSocketCount());
1776 socket_pool->CloseIdleSockets("Close socket reason");
1777 }
1778 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
1779 }
1780 }
1781
1782 // Tests that ERR_MSG_TOO_BIG is retryable for QUIC proxy.
TEST_F(JobControllerReconsiderProxyAfterErrorTest,ReconsiderErrMsgTooBig)1783 TEST_F(JobControllerReconsiderProxyAfterErrorTest, ReconsiderErrMsgTooBig) {
1784 auto quic_proxy_chain =
1785 ProxyChain::ForIpProtection({ProxyServer::FromSchemeHostAndPort(
1786 ProxyServer::SCHEME_QUIC, "bad", 99)});
1787 std::unique_ptr<ConfiguredProxyResolutionService> proxy_resolution_service =
1788 ConfiguredProxyResolutionService::CreateFixedFromProxyChainsForTest(
1789 {quic_proxy_chain, ProxyChain::Direct()},
1790 TRAFFIC_ANNOTATION_FOR_TESTS);
1791
1792 // Before starting the test, verify that there are no proxies marked as bad.
1793 ASSERT_TRUE(proxy_resolution_service->proxy_retry_info().empty());
1794
1795 // Mock data for the QUIC proxy socket.
1796 StaticSocketDataProvider quic_proxy_socket;
1797 quic_proxy_socket.set_connect_data(MockConnect(ASYNC, ERR_MSG_TOO_BIG));
1798 session_deps_.socket_factory->AddSocketDataProvider(&quic_proxy_socket);
1799
1800 // Mock data for DIRECT.
1801 StaticSocketDataProvider socket_data_direct;
1802 socket_data_direct.set_connect_data(MockConnect(ASYNC, OK));
1803 session_deps_.socket_factory->AddSocketDataProvider(&socket_data_direct);
1804
1805 // Now request a stream. It should fall back to DIRECT on ERR_MSG_TOO_BIG.
1806 HttpRequestInfo request_info;
1807 request_info.method = "GET";
1808 request_info.url = GURL("http://www.example.com");
1809
1810 Initialize(std::move(proxy_resolution_service));
1811
1812 ProxyInfo used_proxy_info;
1813 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
1814 .Times(1)
1815 .WillOnce(::testing::SaveArg<0>(&used_proxy_info));
1816
1817 std::unique_ptr<HttpStreamRequest> request =
1818 CreateJobController(request_info);
1819 base::RunLoop().RunUntilIdle();
1820
1821 EXPECT_TRUE(used_proxy_info.is_direct());
1822 const ProxyRetryInfoMap& retry_info =
1823 session_->proxy_resolution_service()->proxy_retry_info();
1824 EXPECT_THAT(retry_info, SizeIs(1));
1825 EXPECT_THAT(retry_info, Contains(Key(quic_proxy_chain)));
1826
1827 request.reset();
1828 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
1829 }
1830
1831 // Same as test above except that this is testing the retry behavior for
1832 // non-QUIC proxy on ERR_MSG_TOO_BIG.
TEST_F(JobControllerReconsiderProxyAfterErrorTest,DoNotReconsiderErrMsgTooBig)1833 TEST_F(JobControllerReconsiderProxyAfterErrorTest,
1834 DoNotReconsiderErrMsgTooBig) {
1835 std::unique_ptr<ConfiguredProxyResolutionService> proxy_resolution_service =
1836 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
1837 "HTTPS badproxy:99; DIRECT", TRAFFIC_ANNOTATION_FOR_TESTS);
1838
1839 // Before starting the test, verify that there are no proxies marked as bad.
1840 ASSERT_TRUE(proxy_resolution_service->proxy_retry_info().empty());
1841
1842 // Mock data for the HTTPS proxy socket.
1843 static constexpr char kHttpConnect[] =
1844 "CONNECT www.example.com:443 HTTP/1.1\r\n"
1845 "Host: www.example.com:443\r\n"
1846 "Proxy-Connection: keep-alive\r\n\r\n";
1847 const MockWrite kWrites[] = {{ASYNC, kHttpConnect}};
1848 const MockRead kReads[] = {{ASYNC, ERR_MSG_TOO_BIG}};
1849 SSLSocketDataProvider ssl_data(ASYNC, OK);
1850 StaticSocketDataProvider https_proxy_socket(kReads, kWrites);
1851 https_proxy_socket.set_connect_data(MockConnect(ASYNC, OK));
1852 session_deps_.socket_factory->AddSocketDataProvider(&https_proxy_socket);
1853 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
1854
1855 // Now request a stream. It should not fallback to DIRECT on ERR_MSG_TOO_BIG.
1856 HttpRequestInfo request_info;
1857 request_info.method = "GET";
1858 request_info.url = GURL("https://www.example.com");
1859
1860 Initialize(std::move(proxy_resolution_service));
1861
1862 ProxyInfo used_proxy_info;
1863 EXPECT_CALL(request_delegate_, OnStreamFailed(ERR_MSG_TOO_BIG, _, _, _))
1864 .Times(1);
1865
1866 std::unique_ptr<HttpStreamRequest> request =
1867 CreateJobController(request_info);
1868 base::RunLoop().RunUntilIdle();
1869
1870 const ProxyRetryInfoMap& retry_info =
1871 session_->proxy_resolution_service()->proxy_retry_info();
1872 EXPECT_THAT(retry_info, SizeIs(0));
1873
1874 request.reset();
1875 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
1876 }
1877
TEST_P(HttpStreamFactoryJobControllerTest,OnStreamFailedWithNoAlternativeJob)1878 TEST_P(HttpStreamFactoryJobControllerTest, OnStreamFailedWithNoAlternativeJob) {
1879 tcp_data_ = std::make_unique<SequencedSocketData>();
1880 tcp_data_->set_connect_data(MockConnect(ASYNC, ERR_FAILED));
1881
1882 HttpRequestInfo request_info;
1883 request_info.method = "GET";
1884 request_info.url = GURL("http://www.google.com");
1885
1886 Initialize(request_info);
1887
1888 request_ =
1889 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
1890 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
1891
1892 EXPECT_TRUE(job_controller_->main_job());
1893 EXPECT_FALSE(job_controller_->alternative_job());
1894
1895 // There's no other alternative job. Thus when stream failed, it should
1896 // notify Request of the stream failure.
1897 EXPECT_CALL(request_delegate_, OnStreamFailed(ERR_FAILED, _, _, _)).Times(1);
1898 base::RunLoop().RunUntilIdle();
1899 }
1900
TEST_P(HttpStreamFactoryJobControllerTest,OnStreamReadyWithNoAlternativeJob)1901 TEST_P(HttpStreamFactoryJobControllerTest, OnStreamReadyWithNoAlternativeJob) {
1902 tcp_data_ = std::make_unique<SequencedSocketData>();
1903 tcp_data_->set_connect_data(MockConnect(ASYNC, OK));
1904
1905 HttpRequestInfo request_info;
1906 request_info.method = "GET";
1907 request_info.url = GURL("http://www.google.com");
1908
1909 Initialize(request_info);
1910
1911 request_ =
1912 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
1913 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
1914
1915 // There's no other alternative job. Thus when a stream is ready, it should
1916 // notify Request.
1917 EXPECT_TRUE(job_controller_->main_job());
1918
1919 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _));
1920 base::RunLoop().RunUntilIdle();
1921 }
1922
1923 // Test we cancel Jobs correctly when the Request is explicitly canceled
1924 // before any Job is bound to Request.
TEST_P(HttpStreamFactoryJobControllerTest,CancelJobsBeforeBinding)1925 TEST_P(HttpStreamFactoryJobControllerTest, CancelJobsBeforeBinding) {
1926 // Use COLD_START to make the alt job pending.
1927 crypto_client_stream_factory_.set_handshake_mode(
1928 MockCryptoClientStream::COLD_START);
1929 quic_data_ = std::make_unique<MockQuicData>(version_);
1930 quic_data_->AddRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED);
1931
1932 tcp_data_ = std::make_unique<SequencedSocketData>();
1933 tcp_data_->set_connect_data(MockConnect(ASYNC, OK));
1934 HttpRequestInfo request_info;
1935 request_info.method = "GET";
1936 request_info.url = GURL("https://www.google.com");
1937
1938 Initialize(request_info);
1939 url::SchemeHostPort server(request_info.url);
1940 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
1941 SetAlternativeService(request_info, alternative_service);
1942
1943 request_ =
1944 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
1945 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
1946 EXPECT_TRUE(job_controller_->main_job());
1947 EXPECT_TRUE(job_controller_->alternative_job());
1948 // Reset the Request will cancel all the Jobs since there's no Job determined
1949 // to serve Request yet and JobController will notify the factory to delete
1950 // itself upon completion.
1951 request_.reset();
1952 // QuicSessionPool::Job::Request will not complete since the Jobs are
1953 // canceled, so there is no need to check if all read data was consumed.
1954 should_check_data_consumed_ = false;
1955 VerifyBrokenAlternateProtocolMapping(request_info, false);
1956 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
1957 }
1958
1959 // Test that the controller does not create alternative job when the advertised
1960 // versions in AlternativeServiceInfo do not contain any version that is
1961 // supported.
TEST_P(HttpStreamFactoryJobControllerTest,DoNotCreateAltJobIfQuicVersionsUnsupported)1962 TEST_P(HttpStreamFactoryJobControllerTest,
1963 DoNotCreateAltJobIfQuicVersionsUnsupported) {
1964 tcp_data_ = std::make_unique<SequencedSocketData>();
1965 tcp_data_->set_connect_data(MockConnect(ASYNC, OK));
1966 HttpRequestInfo request_info;
1967 request_info.method = "GET";
1968 request_info.url = GURL("https://www.google.com");
1969
1970 Initialize(request_info);
1971 url::SchemeHostPort server(request_info.url);
1972 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
1973 base::Time expiration = base::Time::Now() + base::Days(1);
1974 session_->http_server_properties()->SetQuicAlternativeService(
1975 server, NetworkAnonymizationKey(), alternative_service, expiration,
1976 {quic::ParsedQuicVersion::Unsupported()});
1977
1978 request_ =
1979 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
1980 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
1981 EXPECT_TRUE(job_controller_->main_job());
1982 EXPECT_FALSE(job_controller_->alternative_job());
1983
1984 request_.reset();
1985 VerifyBrokenAlternateProtocolMapping(request_info, false);
1986 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
1987 }
1988
1989 void HttpStreamFactoryJobControllerTestBase::
TestDoNotDelayMainJobIfQuicWasRecentlyBroken(bool async_quic_session)1990 TestDoNotDelayMainJobIfQuicWasRecentlyBroken(bool async_quic_session) {
1991 SetAsyncQuicSession(async_quic_session);
1992 crypto_client_stream_factory_.set_handshake_mode(
1993 MockCryptoClientStream::COLD_START);
1994 quic_data_ = std::make_unique<MockQuicData>(version_);
1995 quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
1996 tcp_data_ = std::make_unique<SequencedSocketData>();
1997 tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
1998
1999 HttpRequestInfo request_info;
2000 request_info.method = "GET";
2001 request_info.url = GURL("https://www.google.com");
2002
2003 Initialize(request_info);
2004 url::SchemeHostPort server(request_info.url);
2005 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
2006 base::Time expiration = base::Time::Now() + base::Days(1);
2007 session_->http_server_properties()->SetQuicAlternativeService(
2008 server, NetworkAnonymizationKey(), alternative_service, expiration,
2009 quic_context_.params()->supported_versions);
2010
2011 // Enable QUIC but mark the alternative service as recently broken.
2012 QuicSessionPool* quic_session_pool = session_->quic_session_pool();
2013 quic_session_pool->set_is_quic_known_to_work_on_current_network(true);
2014 session_->http_server_properties()->MarkAlternativeServiceRecentlyBroken(
2015 alternative_service, NetworkAnonymizationKey());
2016
2017 request_ =
2018 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2019 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2020
2021 EXPECT_TRUE(job_controller_->main_job());
2022 EXPECT_TRUE(job_controller_->alternative_job());
2023
2024 // The main job shouldn't have any delay since QUIC was recently broken. Main
2025 // job should still be blocked as alt job has not succeeded or failed at least
2026 // once yet.
2027 EXPECT_EQ(job_controller_->get_main_job_wait_time_for_tests(),
2028 base::TimeDelta());
2029 if (async_quic_session) {
2030 EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_));
2031 } else {
2032 EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
2033 }
2034 // Make |alternative_job| succeed.
2035 auto http_stream = std::make_unique<HttpBasicStream>(
2036 std::make_unique<ClientSocketHandle>(), false);
2037 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, http_stream.get()));
2038
2039 HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(),
2040 std::move(http_stream));
2041 job_controller_->OnStreamReady(job_factory_.alternative_job());
2042
2043 base::RunLoop().RunUntilIdle();
2044
2045 // Check that alternative job is bound while main job is destroyed.
2046 EXPECT_FALSE(job_controller_->main_job());
2047 EXPECT_TRUE(job_controller_->alternative_job());
2048
2049 request_.reset();
2050 VerifyBrokenAlternateProtocolMapping(request_info, false);
2051 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2052 }
2053
TEST_P(HttpStreamFactoryJobControllerTest,DoNotDelayMainJobIfQuicWasRecentlyBroken)2054 TEST_P(HttpStreamFactoryJobControllerTest,
2055 DoNotDelayMainJobIfQuicWasRecentlyBroken) {
2056 TestDoNotDelayMainJobIfQuicWasRecentlyBroken(false);
2057 }
2058
TEST_P(HttpStreamFactoryJobControllerTest,DoNotDelayMainJobIfQuicWasRecentlyBrokenAsyncQuicSession)2059 TEST_P(HttpStreamFactoryJobControllerTest,
2060 DoNotDelayMainJobIfQuicWasRecentlyBrokenAsyncQuicSession) {
2061 TestDoNotDelayMainJobIfQuicWasRecentlyBroken(true);
2062 }
2063
2064 void HttpStreamFactoryJobControllerTestBase::
TestDelayMainJobAfterRecentlyBrokenQuicWasConfirmed(bool async_quic_session)2065 TestDelayMainJobAfterRecentlyBrokenQuicWasConfirmed(
2066 bool async_quic_session) {
2067 SetAsyncQuicSession(async_quic_session);
2068 crypto_client_stream_factory_.set_handshake_mode(
2069 MockCryptoClientStream::COLD_START);
2070 quic_data_ = std::make_unique<MockQuicData>(version_);
2071 quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
2072 tcp_data_ = std::make_unique<SequencedSocketData>();
2073 tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
2074
2075 HttpRequestInfo request_info;
2076 request_info.method = "GET";
2077 request_info.url = GURL("https://www.google.com");
2078
2079 Initialize(request_info);
2080 url::SchemeHostPort server(request_info.url);
2081 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
2082 base::Time expiration = base::Time::Now() + base::Days(1);
2083 session_->http_server_properties()->SetQuicAlternativeService(
2084 server, NetworkAnonymizationKey(), alternative_service, expiration,
2085 quic_context_.params()->supported_versions);
2086
2087 // Enable QUIC but mark the alternative service as recently broken.
2088 QuicSessionPool* quic_session_pool = session_->quic_session_pool();
2089 quic_session_pool->set_is_quic_known_to_work_on_current_network(true);
2090 session_->http_server_properties()->MarkAlternativeServiceRecentlyBroken(
2091 alternative_service, NetworkAnonymizationKey());
2092
2093 // Confirm the alt service.
2094 session_->http_server_properties()->ConfirmAlternativeService(
2095 alternative_service, NetworkAnonymizationKey());
2096
2097 request_ =
2098 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2099 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2100
2101 EXPECT_TRUE(job_controller_->main_job());
2102 EXPECT_TRUE(job_controller_->alternative_job());
2103
2104 // The main job should wait and it should still be blocked because the new
2105 // QUIC session hasn't been created yet. The wait time should be greater than
2106 // 0.
2107 EXPECT_TRUE(job_controller_->ShouldWait(
2108 const_cast<net::HttpStreamFactory::Job*>(job_controller_->main_job())));
2109 if (async_quic_session) {
2110 EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_));
2111 } else {
2112 EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
2113 }
2114 EXPECT_GE(job_controller_->get_main_job_wait_time_for_tests(),
2115 base::TimeDelta());
2116
2117 // Make |alternative_job| succeed.
2118 auto http_stream = std::make_unique<HttpBasicStream>(
2119 std::make_unique<ClientSocketHandle>(), false);
2120 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, http_stream.get()));
2121
2122 HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(),
2123 std::move(http_stream));
2124 job_controller_->OnStreamReady(job_factory_.alternative_job());
2125
2126 base::RunLoop().RunUntilIdle();
2127
2128 // Check that alternative job is bound while main job is destroyed.
2129 EXPECT_FALSE(job_controller_->main_job());
2130 EXPECT_TRUE(job_controller_->alternative_job());
2131
2132 request_.reset();
2133 VerifyBrokenAlternateProtocolMapping(request_info, false);
2134 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2135 }
2136
TEST_P(HttpStreamFactoryJobControllerTest,DelayMainJobAfterRecentlyBrokenQuicWasConfirmed)2137 TEST_P(HttpStreamFactoryJobControllerTest,
2138 DelayMainJobAfterRecentlyBrokenQuicWasConfirmed) {
2139 TestDelayMainJobAfterRecentlyBrokenQuicWasConfirmed(false);
2140 }
2141
TEST_P(HttpStreamFactoryJobControllerTest,DelayMainJobAfterRecentlyBrokenQuicWasConfirmedAsyncQuicSession)2142 TEST_P(HttpStreamFactoryJobControllerTest,
2143 DelayMainJobAfterRecentlyBrokenQuicWasConfirmedAsyncQuicSession) {
2144 TestDelayMainJobAfterRecentlyBrokenQuicWasConfirmed(true);
2145 }
2146
TestOnStreamFailedForBothJobs(bool alt_job_retried_on_non_default_network,bool async_quic_session)2147 void HttpStreamFactoryJobControllerTestBase::TestOnStreamFailedForBothJobs(
2148 bool alt_job_retried_on_non_default_network,
2149 bool async_quic_session) {
2150 SetAsyncQuicSession(async_quic_session);
2151 quic_data_ = std::make_unique<MockQuicData>(version_);
2152 quic_data_->AddConnect(ASYNC, ERR_FAILED);
2153 tcp_data_ = std::make_unique<SequencedSocketData>();
2154 tcp_data_->set_connect_data(MockConnect(ASYNC, ERR_FAILED));
2155
2156 HttpRequestInfo request_info;
2157 request_info.method = "GET";
2158 request_info.url = GURL("https://www.google.com");
2159
2160 Initialize(request_info);
2161 url::SchemeHostPort server(request_info.url);
2162 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
2163 SetAlternativeService(request_info, alternative_service);
2164
2165 request_ =
2166 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2167 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2168 EXPECT_TRUE(job_controller_->main_job());
2169 EXPECT_TRUE(job_controller_->alternative_job());
2170
2171 if (alt_job_retried_on_non_default_network) {
2172 // Set the alt job as if it failed on the default network and is retired on
2173 // the alternate network.
2174 JobControllerPeer::SetAltJobFailedOnDefaultNetwork(job_controller_);
2175 }
2176
2177 if (async_quic_session) {
2178 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() {
2179 job_factory_.main_job()->DoResume();
2180 });
2181 }
2182 // The failure of second Job should be reported to Request as there's no more
2183 // pending Job to serve the Request.
2184 EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _, _)).Times(1);
2185 base::RunLoop().RunUntilIdle();
2186 VerifyBrokenAlternateProtocolMapping(request_info, false);
2187 request_.reset();
2188 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2189 }
2190
2191 // This test verifies that the alternative service is not marked broken if both
2192 // jobs fail, and the alternative job is not retried on the alternate network.
TEST_P(HttpStreamFactoryJobControllerTest,OnStreamFailedForBothJobsWithoutQuicRetry)2193 TEST_P(HttpStreamFactoryJobControllerTest,
2194 OnStreamFailedForBothJobsWithoutQuicRetry) {
2195 TestOnStreamFailedForBothJobs(false, false);
2196 }
2197
2198 // This test verifies that the alternative service is not marked broken if both
2199 // jobs fail, and the alternative job is retried on the alternate network.
TEST_P(HttpStreamFactoryJobControllerTest,OnStreamFailedForBothJobsWithQuicRetriedOnAlternateNetwork)2200 TEST_P(HttpStreamFactoryJobControllerTest,
2201 OnStreamFailedForBothJobsWithQuicRetriedOnAlternateNetwork) {
2202 TestOnStreamFailedForBothJobs(true, false);
2203 }
2204
2205 // This test verifies that the alternative service is not marked broken if both
2206 // jobs fail, and the alternative job is not retried on the alternate network.
2207 // This test uses asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,OnStreamFailedForBothJobsWithoutQuicRetryAsyncQuicSession)2208 TEST_P(HttpStreamFactoryJobControllerTest,
2209 OnStreamFailedForBothJobsWithoutQuicRetryAsyncQuicSession) {
2210 TestOnStreamFailedForBothJobs(false, true);
2211 }
2212
2213 // This test verifies that the alternative service is not marked broken if both
2214 // jobs fail, and the alternative job is retried on the alternate network. This
2215 // test uses asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,OnStreamFailedForBothJobsWithQuicRetriedOnAlternateNetworkAsyncQuicSession)2216 TEST_P(
2217 HttpStreamFactoryJobControllerTest,
2218 OnStreamFailedForBothJobsWithQuicRetriedOnAlternateNetworkAsyncQuicSession) {
2219 TestOnStreamFailedForBothJobs(true, true);
2220 }
2221
2222 void HttpStreamFactoryJobControllerTestBase::
TestAltJobFailsAfterMainJobSucceeded(bool alt_job_retried_on_non_default_network,bool async_quic_session)2223 TestAltJobFailsAfterMainJobSucceeded(
2224 bool alt_job_retried_on_non_default_network,
2225 bool async_quic_session) {
2226 SetAsyncQuicSession(async_quic_session);
2227 quic_data_ = std::make_unique<MockQuicData>(version_);
2228 quic_data_->AddRead(ASYNC, ERR_FAILED);
2229 crypto_client_stream_factory_.set_handshake_mode(
2230 MockCryptoClientStream::COLD_START);
2231
2232 tcp_data_ = std::make_unique<SequencedSocketData>();
2233 tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
2234 SSLSocketDataProvider ssl_data(SYNCHRONOUS, OK);
2235 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
2236
2237 HttpRequestInfo request_info;
2238 request_info.method = "GET";
2239 request_info.url = GURL("https://www.google.com");
2240
2241 Initialize(request_info);
2242 url::SchemeHostPort server(request_info.url);
2243 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
2244 SetAlternativeService(request_info, alternative_service);
2245
2246 request_ =
2247 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2248 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2249 EXPECT_TRUE(job_controller_->main_job());
2250 EXPECT_TRUE(job_controller_->alternative_job());
2251
2252 if (alt_job_retried_on_non_default_network) {
2253 // Set the alt job as if it failed on the default network and is retired on
2254 // the alternate network.
2255 JobControllerPeer::SetAltJobFailedOnDefaultNetwork(job_controller_);
2256 }
2257
2258 if (async_quic_session) {
2259 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() {
2260 job_factory_.main_job()->DoResume();
2261 });
2262 }
2263 // Main job succeeds, starts serving Request and it should report status
2264 // to Request. The alternative job will mark the main job complete and gets
2265 // orphaned.
2266 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _));
2267 // JobController shouldn't report the status of second job as request
2268 // is already successfully served.
2269 EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _, _)).Times(0);
2270
2271 base::RunLoop().RunUntilIdle();
2272
2273 // Reset the request as it's been successfully served.
2274 request_.reset();
2275 base::RunLoop().RunUntilIdle();
2276 VerifyBrokenAlternateProtocolMapping(request_info, true);
2277 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2278
2279 // Verify the brokenness is not cleared when the default network changes.
2280 session_->http_server_properties()->OnDefaultNetworkChanged();
2281 VerifyBrokenAlternateProtocolMapping(request_info, true);
2282 }
2283
2284 // This test verifies that the alternative service is marked broken when the
2285 // alternative job fails on default after the main job succeeded. The
2286 // brokenness should not be cleared when the default network changes.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobFailsOnDefaultNetworkAfterMainJobSucceeded)2287 TEST_P(HttpStreamFactoryJobControllerTest,
2288 AltJobFailsOnDefaultNetworkAfterMainJobSucceeded) {
2289 TestAltJobFailsAfterMainJobSucceeded(false, false);
2290 }
2291
2292 // This test verifies that the alternative service is marked broken when the
2293 // alternative job fails on both networks after the main job succeeded. The
2294 // brokenness should not be cleared when the default network changes.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobFailsOnBothNetworksAfterMainJobSucceeded)2295 TEST_P(HttpStreamFactoryJobControllerTest,
2296 AltJobFailsOnBothNetworksAfterMainJobSucceeded) {
2297 TestAltJobFailsAfterMainJobSucceeded(true, false);
2298 }
2299
2300 // This test verifies that the alternative service is marked broken when the
2301 // alternative job fails on default after the main job succeeded. The
2302 // brokenness should not be cleared when the default network changes. This test
2303 // uses asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobFailsOnDefaultNetworkAfterMainJobSucceededAsyncQuicSession)2304 TEST_P(HttpStreamFactoryJobControllerTest,
2305 AltJobFailsOnDefaultNetworkAfterMainJobSucceededAsyncQuicSession) {
2306 TestAltJobFailsAfterMainJobSucceeded(false, true);
2307 }
2308
2309 // This test verifies that the alternative service is marked broken when the
2310 // alternative job fails on both networks after the main job succeeded. The
2311 // brokenness should not be cleared when the default network changes. This test
2312 // uses asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobFailsOnBothNetworksAfterMainJobSucceededAsyncQuicSession)2313 TEST_P(HttpStreamFactoryJobControllerTest,
2314 AltJobFailsOnBothNetworksAfterMainJobSucceededAsyncQuicSession) {
2315 TestAltJobFailsAfterMainJobSucceeded(true, true);
2316 }
2317
TestAltJobSucceedsMainJobDestroyed(bool async_quic_session)2318 void HttpStreamFactoryJobControllerTestBase::TestAltJobSucceedsMainJobDestroyed(
2319 bool async_quic_session) {
2320 SetAsyncQuicSession(async_quic_session);
2321 quic_data_ = std::make_unique<MockQuicData>(version_);
2322 quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
2323 // Use cold start and complete alt job manually.
2324 crypto_client_stream_factory_.set_handshake_mode(
2325 MockCryptoClientStream::COLD_START);
2326 tcp_data_ = std::make_unique<SequencedSocketData>();
2327 tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
2328
2329 HttpRequestInfo request_info;
2330 request_info.method = "GET";
2331 request_info.url = GURL("https://www.google.com");
2332
2333 Initialize(request_info);
2334
2335 url::SchemeHostPort server(request_info.url);
2336 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
2337 SetAlternativeService(request_info, alternative_service);
2338 request_ =
2339 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2340 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2341 EXPECT_TRUE(job_controller_->main_job());
2342 EXPECT_TRUE(job_controller_->alternative_job());
2343 if (async_quic_session) {
2344 EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_));
2345 } else {
2346 EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
2347 }
2348 // Make |alternative_job| succeed.
2349 auto http_stream = std::make_unique<HttpBasicStream>(
2350 std::make_unique<ClientSocketHandle>(), false);
2351 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, http_stream.get()));
2352
2353 HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(),
2354 std::move(http_stream));
2355 job_controller_->OnStreamReady(job_factory_.alternative_job());
2356
2357 base::RunLoop().RunUntilIdle();
2358
2359 EXPECT_FALSE(job_controller_->main_job());
2360 EXPECT_TRUE(job_controller_->alternative_job());
2361
2362 request_.reset();
2363 VerifyBrokenAlternateProtocolMapping(request_info, false);
2364 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2365 }
2366
2367 // Tests that when alt job succeeds, main job is destroyed.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobSucceedsMainJobDestroyed)2368 TEST_P(HttpStreamFactoryJobControllerTest, AltJobSucceedsMainJobDestroyed) {
2369 TestAltJobSucceedsMainJobDestroyed(false);
2370 }
2371
2372 // Tests that when alt job succeeds, main job is destroyed.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobSucceedsMainJobDestroyedAsyncQuicSession)2373 TEST_P(HttpStreamFactoryJobControllerTest,
2374 AltJobSucceedsMainJobDestroyedAsyncQuicSession) {
2375 TestAltJobSucceedsMainJobDestroyed(true);
2376 }
2377
2378 // Tests that if alt job succeeds and main job is blocked, main job should be
2379 // cancelled immediately. |request_| completion will clean up the JobController.
2380 // Regression test for crbug.com/678768.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobSucceedsMainJobBlockedControllerDestroyed)2381 TEST_P(HttpStreamFactoryJobControllerTest,
2382 AltJobSucceedsMainJobBlockedControllerDestroyed) {
2383 quic_data_ = std::make_unique<MockQuicData>(version_);
2384 quic_data_->AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
2385 quic_data_->AddRead(ASYNC, ERR_CONNECTION_CLOSED);
2386
2387 HttpRequestInfo request_info;
2388 request_info.method = "GET";
2389 request_info.url = GURL("https://www.google.com");
2390
2391 Initialize(request_info);
2392
2393 url::SchemeHostPort server(request_info.url);
2394 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
2395 SetAlternativeService(request_info, alternative_service);
2396 request_ =
2397 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2398 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2399 EXPECT_TRUE(job_controller_->main_job());
2400 EXPECT_TRUE(job_controller_->alternative_job());
2401 EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_));
2402
2403 // |alternative_job| succeeds and should report status to |request_delegate_|.
2404 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _));
2405 base::RunLoop().RunUntilIdle();
2406
2407 EXPECT_FALSE(job_controller_->main_job());
2408 EXPECT_TRUE(job_controller_->alternative_job());
2409
2410 // Invoke OnRequestComplete() which should delete |job_controller_| from
2411 // |factory_|.
2412 request_.reset();
2413 // base::RunLoop().RunUntilIdle();
2414 VerifyBrokenAlternateProtocolMapping(request_info, false);
2415 // This fails without the fix for crbug.com/678768.
2416 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2417 }
2418
TEST_P(HttpStreamFactoryJobControllerTest,SpdySessionKeyHasOriginHostPortPair)2419 TEST_P(HttpStreamFactoryJobControllerTest,
2420 SpdySessionKeyHasOriginHostPortPair) {
2421 session_deps_.enable_http2_alternative_service = true;
2422
2423 const char origin_host[] = "www.example.org";
2424 const uint16_t origin_port = 443;
2425 const char alternative_host[] = "mail.example.org";
2426 const uint16_t alternative_port = 123;
2427
2428 HttpRequestInfo request_info;
2429 request_info.method = "GET";
2430 request_info.url =
2431 GURL(base::StringPrintf("https://%s:%u", origin_host, origin_port));
2432 Initialize(request_info);
2433
2434 url::SchemeHostPort server(request_info.url);
2435 AlternativeService alternative_service(kProtoHTTP2, alternative_host,
2436 alternative_port);
2437 SetAlternativeService(request_info, alternative_service);
2438
2439 request_ =
2440 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2441 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2442
2443 HostPortPair main_host_port_pair =
2444 HttpStreamFactoryJobPeer::GetSpdySessionKey(job_controller_->main_job())
2445 .host_port_pair();
2446 EXPECT_EQ(origin_host, main_host_port_pair.host());
2447 EXPECT_EQ(origin_port, main_host_port_pair.port());
2448
2449 HostPortPair alternative_host_port_pair =
2450 HttpStreamFactoryJobPeer::GetSpdySessionKey(
2451 job_controller_->alternative_job())
2452 .host_port_pair();
2453 EXPECT_EQ(origin_host, alternative_host_port_pair.host());
2454 EXPECT_EQ(origin_port, alternative_host_port_pair.port());
2455 }
2456
2457 void HttpStreamFactoryJobControllerTestBase::
TestOrphanedJobCompletesControllerDestroyed(bool async_quic_session)2458 TestOrphanedJobCompletesControllerDestroyed(bool async_quic_session) {
2459 SetAsyncQuicSession(async_quic_session);
2460 quic_data_ = std::make_unique<MockQuicData>(version_);
2461 quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
2462 // Use cold start and complete alt job manually.
2463 crypto_client_stream_factory_.set_handshake_mode(
2464 MockCryptoClientStream::COLD_START);
2465
2466 tcp_data_ = std::make_unique<SequencedSocketData>();
2467 tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
2468 SSLSocketDataProvider ssl_data(ASYNC, OK);
2469 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
2470
2471 HttpRequestInfo request_info;
2472 request_info.method = "GET";
2473 request_info.url = GURL("https://www.google.com");
2474
2475 Initialize(request_info);
2476
2477 url::SchemeHostPort server(request_info.url);
2478 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
2479 SetAlternativeService(request_info, alternative_service);
2480
2481 request_ =
2482 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2483 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2484 EXPECT_TRUE(job_controller_->main_job());
2485 EXPECT_TRUE(job_controller_->alternative_job());
2486
2487 if (async_quic_session) {
2488 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() {
2489 job_factory_.main_job()->DoResume();
2490 });
2491 }
2492
2493 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _));
2494
2495 // Complete main job now.
2496 base::RunLoop().RunUntilIdle();
2497
2498 // Invoke OnRequestComplete() which should not delete |job_controller_| from
2499 // |factory_| because alt job is yet to finish.
2500 request_.reset();
2501 ASSERT_FALSE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2502 EXPECT_FALSE(job_controller_->main_job());
2503 EXPECT_TRUE(job_controller_->alternative_job());
2504
2505 // Make |alternative_job| succeed.
2506 auto http_stream = std::make_unique<HttpBasicStream>(
2507 std::make_unique<ClientSocketHandle>(), false);
2508 HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(),
2509 std::move(http_stream));
2510 // This should not call request_delegate_::OnStreamReady.
2511 job_controller_->OnStreamReady(job_factory_.alternative_job());
2512 // Make sure that controller does not leak.
2513 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2514 }
2515
2516 // Tests that if an orphaned job completes after |request_| is gone,
2517 // JobController will be cleaned up.
TEST_P(HttpStreamFactoryJobControllerTest,OrphanedJobCompletesControllerDestroyed)2518 TEST_P(HttpStreamFactoryJobControllerTest,
2519 OrphanedJobCompletesControllerDestroyed) {
2520 TestOrphanedJobCompletesControllerDestroyed(false);
2521 }
2522
2523 // Tests that if an orphaned job completes after |request_| is gone,
2524 // JobController will be cleaned up.
TEST_P(HttpStreamFactoryJobControllerTest,OrphanedJobCompletesControllerDestroyedAsyncQuicSession)2525 TEST_P(HttpStreamFactoryJobControllerTest,
2526 OrphanedJobCompletesControllerDestroyedAsyncQuicSession) {
2527 TestOrphanedJobCompletesControllerDestroyed(true);
2528 }
2529
2530 void HttpStreamFactoryJobControllerTestBase::
TestAltJobSucceedsAfterMainJobFailed(bool alt_job_retried_on_non_default_network,bool async_quic_session)2531 TestAltJobSucceedsAfterMainJobFailed(
2532 bool alt_job_retried_on_non_default_network,
2533 bool async_quic_session) {
2534 SetAsyncQuicSession(async_quic_session);
2535 quic_data_ = std::make_unique<MockQuicData>(version_);
2536 quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
2537 // Use cold start and complete alt job manually.
2538 crypto_client_stream_factory_.set_handshake_mode(
2539 MockCryptoClientStream::COLD_START);
2540
2541 // One failed TCP connect.
2542 tcp_data_ = std::make_unique<SequencedSocketData>();
2543 tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, ERR_FAILED));
2544
2545 HttpRequestInfo request_info;
2546 request_info.method = "GET";
2547 request_info.url = GURL("https://www.google.com");
2548
2549 Initialize(request_info);
2550
2551 url::SchemeHostPort server(request_info.url);
2552 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
2553 SetAlternativeService(request_info, alternative_service);
2554
2555 // |main_job| fails but should not report status to Request.
2556 EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _, _)).Times(0);
2557
2558 request_ =
2559 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2560 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2561 EXPECT_TRUE(job_controller_->main_job());
2562 EXPECT_TRUE(job_controller_->alternative_job());
2563
2564 if (alt_job_retried_on_non_default_network) {
2565 // Set the alt job as if it failed on the default network and is retried on
2566 // the alternate network.
2567 JobControllerPeer::SetAltJobFailedOnDefaultNetwork(job_controller_);
2568 }
2569
2570 // Make |alternative_job| succeed.
2571 auto http_stream = std::make_unique<HttpBasicStream>(
2572 std::make_unique<ClientSocketHandle>(), false);
2573 if (async_quic_session) {
2574 base::RunLoop run_loop;
2575 EXPECT_CALL(*job_factory_.main_job(), Resume())
2576 .Times(1)
2577 .WillOnce([&run_loop, this]() {
2578 run_loop.Quit();
2579 job_factory_.main_job()->DoResume();
2580 });
2581 run_loop.Run();
2582 }
2583 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, http_stream.get()));
2584
2585 HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(),
2586 std::move(http_stream));
2587 job_controller_->OnStreamReady(job_factory_.alternative_job());
2588 base::RunLoop().RunUntilIdle();
2589 // |alternative_job| succeeds and should report status to Request.
2590 VerifyBrokenAlternateProtocolMapping(request_info, false);
2591 request_.reset();
2592 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2593 }
2594
2595 // This test verifies that the alternative service is not mark broken if the
2596 // alternative job succeeds on the default network after the main job failed.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobSucceedsOnDefaultNetworkAfterMainJobFailed)2597 TEST_P(HttpStreamFactoryJobControllerTest,
2598 AltJobSucceedsOnDefaultNetworkAfterMainJobFailed) {
2599 TestAltJobSucceedsAfterMainJobFailed(false, false);
2600 }
2601
2602 // This test verifies that the alternative service is not mark broken if the
2603 // alternative job succeeds on the alternate network after the main job failed.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobSucceedsOnAlternateNetworkAfterMainJobFailed)2604 TEST_P(HttpStreamFactoryJobControllerTest,
2605 AltJobSucceedsOnAlternateNetworkAfterMainJobFailed) {
2606 TestAltJobSucceedsAfterMainJobFailed(true, false);
2607 }
2608
2609 // This test verifies that the alternative service is not mark broken if the
2610 // alternative job succeeds on the default network after the main job failed.
2611 // This test uses asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobSucceedsOnDefaultNetworkAfterMainJobFailedAsyncQuicSession)2612 TEST_P(HttpStreamFactoryJobControllerTest,
2613 AltJobSucceedsOnDefaultNetworkAfterMainJobFailedAsyncQuicSession) {
2614 TestAltJobSucceedsAfterMainJobFailed(false, true);
2615 }
2616
2617 // This test verifies that the alternative service is not mark broken if the
2618 // alternative job succeeds on the alternate network after the main job failed.
2619 // This test uses asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobSucceedsOnAlternateNetworkAfterMainJobFailedAsyncQuicSession)2620 TEST_P(HttpStreamFactoryJobControllerTest,
2621 AltJobSucceedsOnAlternateNetworkAfterMainJobFailedAsyncQuicSession) {
2622 TestAltJobSucceedsAfterMainJobFailed(true, true);
2623 }
2624
2625 void HttpStreamFactoryJobControllerTestBase::
TestAltJobSucceedsAfterMainJobSucceeded(bool alt_job_retried_on_non_default_network,bool async_quic_session)2626 TestAltJobSucceedsAfterMainJobSucceeded(
2627 bool alt_job_retried_on_non_default_network,
2628 bool async_quic_session) {
2629 SetAsyncQuicSession(async_quic_session);
2630 quic_data_ = std::make_unique<MockQuicData>(version_);
2631 quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
2632 // Use cold start and complete alt job manually.
2633 crypto_client_stream_factory_.set_handshake_mode(
2634 MockCryptoClientStream::COLD_START);
2635
2636 tcp_data_ = std::make_unique<SequencedSocketData>();
2637 tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
2638 SSLSocketDataProvider ssl_data(ASYNC, OK);
2639 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
2640
2641 HttpRequestInfo request_info;
2642 request_info.method = "GET";
2643 request_info.url = GURL("https://www.google.com");
2644
2645 Initialize(request_info);
2646
2647 url::SchemeHostPort server(request_info.url);
2648 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
2649 SetAlternativeService(request_info, alternative_service);
2650
2651 // |main_job| fails but should not report status to Request.
2652 EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _, _)).Times(0);
2653
2654 request_ =
2655 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2656 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2657 EXPECT_TRUE(job_controller_->main_job());
2658 EXPECT_TRUE(job_controller_->alternative_job());
2659
2660 if (async_quic_session) {
2661 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() {
2662 job_factory_.main_job()->DoResume();
2663 });
2664 }
2665
2666 // Run the message loop to make |main_job| succeed and status will be
2667 // reported to Request.
2668 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _));
2669 base::RunLoop().RunUntilIdle();
2670 VerifyBrokenAlternateProtocolMapping(request_info, false);
2671
2672 if (alt_job_retried_on_non_default_network) {
2673 // Set the alt job as if it failed on the default network and is retired on
2674 // the alternate network.
2675 JobControllerPeer::SetAltJobFailedOnDefaultNetwork(job_controller_);
2676 }
2677
2678 // Make |alternative_job| succeed.
2679 auto http_stream = std::make_unique<HttpBasicStream>(
2680 std::make_unique<ClientSocketHandle>(), false);
2681
2682 HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(),
2683 std::move(http_stream));
2684 job_controller_->OnStreamReady(job_factory_.alternative_job());
2685
2686 request_.reset();
2687 // If alt job was retried on the alternate network, the alternative service
2688 // should be marked broken until the default network changes.
2689 VerifyBrokenAlternateProtocolMapping(request_info,
2690 alt_job_retried_on_non_default_network);
2691 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2692 if (alt_job_retried_on_non_default_network) {
2693 // Verify the brokenness is cleared when the default network changes.
2694 session_->http_server_properties()->OnDefaultNetworkChanged();
2695 VerifyBrokenAlternateProtocolMapping(request_info, false);
2696 }
2697 }
2698
2699 // This test verifies that the alternative service is not marked broken if the
2700 // alternative job succeeds on the default network after the main job succeeded.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobSucceedsOnDefaultNetworkAfterMainJobSucceeded)2701 TEST_P(HttpStreamFactoryJobControllerTest,
2702 AltJobSucceedsOnDefaultNetworkAfterMainJobSucceeded) {
2703 TestAltJobSucceedsAfterMainJobSucceeded(false, false);
2704 }
2705
2706 // This test verifies that the alternative service is marked broken until the
2707 // default network changes if the alternative job succeeds on the non-default
2708 // network, which failed on the default network previously, after the main job
2709 // succeeded. The brokenness should be cleared when the default network
2710 // changes.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobSucceedsOnAlternateNetworkAfterMainJobSucceeded)2711 TEST_P(HttpStreamFactoryJobControllerTest,
2712 AltJobSucceedsOnAlternateNetworkAfterMainJobSucceeded) {
2713 TestAltJobSucceedsAfterMainJobSucceeded(true, false);
2714 }
2715
2716 // This test verifies that the alternative service is not marked broken if the
2717 // alternative job succeeds on the default network after the main job succeeded.
2718 // This test uses asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobSucceedsOnDefaultNetworkAfterMainJobSucceededAsyncQuicSession)2719 TEST_P(HttpStreamFactoryJobControllerTest,
2720 AltJobSucceedsOnDefaultNetworkAfterMainJobSucceededAsyncQuicSession) {
2721 TestAltJobSucceedsAfterMainJobSucceeded(false, true);
2722 }
2723
2724 // This test verifies that the alternative service is marked broken until the
2725 // default network changes if the alternative job succeeds on the non-default
2726 // network, which failed on the default network previously, after the main job
2727 // succeeded. The brokenness should be cleared when the default network
2728 // changes. This test uses asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,AltJobSucceedsOnAlternateNetworkAfterMainJobSucceededAsyncQuicSession)2729 TEST_P(HttpStreamFactoryJobControllerTest,
2730 AltJobSucceedsOnAlternateNetworkAfterMainJobSucceededAsyncQuicSession) {
2731 TestAltJobSucceedsAfterMainJobSucceeded(true, true);
2732 }
2733
2734 void HttpStreamFactoryJobControllerTestBase::
TestMainJobSucceedsAfterAltJobSucceeded(bool alt_job_retried_on_non_default_network,bool async_quic_session)2735 TestMainJobSucceedsAfterAltJobSucceeded(
2736 bool alt_job_retried_on_non_default_network,
2737 bool async_quic_session) {
2738 SetAsyncQuicSession(async_quic_session);
2739 quic_data_ = std::make_unique<MockQuicData>(version_);
2740 quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
2741 // Use cold start and complete alt job manually.
2742 crypto_client_stream_factory_.set_handshake_mode(
2743 MockCryptoClientStream::COLD_START);
2744
2745 tcp_data_ = std::make_unique<SequencedSocketData>();
2746 tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
2747 SSLSocketDataProvider ssl_data(ASYNC, OK);
2748 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
2749
2750 HttpRequestInfo request_info;
2751 request_info.method = "GET";
2752 request_info.url = GURL("https://www.google.com");
2753
2754 Initialize(request_info);
2755
2756 url::SchemeHostPort server(request_info.url);
2757 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
2758 SetAlternativeService(request_info, alternative_service);
2759
2760 request_ =
2761 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2762 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2763 EXPECT_TRUE(job_controller_->main_job());
2764 EXPECT_TRUE(job_controller_->alternative_job());
2765
2766 if (alt_job_retried_on_non_default_network) {
2767 // Set the alt job as if it failed on the default network and is retired on
2768 // the alternate network.
2769 JobControllerPeer::SetAltJobFailedOnDefaultNetwork(job_controller_);
2770 }
2771 // Make |alternative_job| succeed.
2772 auto http_stream = std::make_unique<HttpBasicStream>(
2773 std::make_unique<ClientSocketHandle>(), false);
2774 if (async_quic_session) {
2775 base::RunLoop run_loop;
2776 EXPECT_CALL(*job_factory_.main_job(), Resume())
2777 .Times(1)
2778 .WillOnce([&run_loop, this]() {
2779 run_loop.Quit();
2780 job_factory_.main_job()->DoResume();
2781 });
2782 run_loop.Run();
2783 }
2784 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, http_stream.get()));
2785
2786 HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(),
2787 std::move(http_stream));
2788 job_controller_->OnStreamReady(job_factory_.alternative_job());
2789
2790 // Run message loop to make the main job succeed.
2791 base::RunLoop().RunUntilIdle();
2792 request_.reset();
2793
2794 // If alt job was retried on the alternate network, the alternative service
2795 // should be marked broken until the default network changes.
2796 VerifyBrokenAlternateProtocolMapping(request_info,
2797 alt_job_retried_on_non_default_network);
2798 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2799 if (alt_job_retried_on_non_default_network) {
2800 // Verify the brokenness is cleared when the default network changes.
2801 session_->http_server_properties()->OnDefaultNetworkChanged();
2802 VerifyBrokenAlternateProtocolMapping(request_info, false);
2803 }
2804 }
2805
2806 // This test verifies that the alternative service is not marked broken if the
2807 // main job succeeds after the alternative job succeeded on the default network.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterAltJobSucceededOnDefaultNetwork)2808 TEST_P(HttpStreamFactoryJobControllerTest,
2809 MainJobSucceedsAfterAltJobSucceededOnDefaultNetwork) {
2810 TestMainJobSucceedsAfterAltJobSucceeded(false, false);
2811 }
2812
2813 // This test verifies that the alternative service is marked broken until the
2814 // default network changes if the main job succeeds after the alternative job
2815 // succeeded on the non-default network, i.e., failed on the default network
2816 // previously. The brokenness should be cleared when the default network
2817 // changes.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterAltJobSucceededOnAlternateNetwork)2818 TEST_P(HttpStreamFactoryJobControllerTest,
2819 MainJobSucceedsAfterAltJobSucceededOnAlternateNetwork) {
2820 TestMainJobSucceedsAfterAltJobSucceeded(true, false);
2821 }
2822
2823 // This test verifies that the alternative service is not marked broken if the
2824 // main job succeeds after the alternative job succeeded on the default network.
2825 // This test uses asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterAltJobSucceededOnDefaultNetworkAsyncQuicSession)2826 TEST_P(HttpStreamFactoryJobControllerTest,
2827 MainJobSucceedsAfterAltJobSucceededOnDefaultNetworkAsyncQuicSession) {
2828 TestMainJobSucceedsAfterAltJobSucceeded(false, true);
2829 }
2830
2831 // This test verifies that the alternative service is marked broken until the
2832 // default network changes if the main job succeeds after the alternative job
2833 // succeeded on the non-default network, i.e., failed on the default network
2834 // previously. The brokenness should be cleared when the default network
2835 // changes. This test uses asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterAltJobSucceededOnAlternateNetworkAsyncQuicSession)2836 TEST_P(HttpStreamFactoryJobControllerTest,
2837 MainJobSucceedsAfterAltJobSucceededOnAlternateNetworkAsyncQuicSession) {
2838 TestMainJobSucceedsAfterAltJobSucceeded(true, true);
2839 }
2840
2841 void HttpStreamFactoryJobControllerTestBase::
TestMainJobFailsAfterAltJobSucceeded(bool alt_job_retried_on_non_default_network,bool async_quic_session)2842 TestMainJobFailsAfterAltJobSucceeded(
2843 bool alt_job_retried_on_non_default_network,
2844 bool async_quic_session) {
2845 SetAsyncQuicSession(async_quic_session);
2846 quic_data_ = std::make_unique<MockQuicData>(version_);
2847 quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
2848 // Use cold start and complete alt job manually.
2849 crypto_client_stream_factory_.set_handshake_mode(
2850 MockCryptoClientStream::COLD_START);
2851
2852 tcp_data_ = std::make_unique<SequencedSocketData>();
2853 tcp_data_->set_connect_data(MockConnect(ASYNC, ERR_FAILED));
2854
2855 HttpRequestInfo request_info;
2856 request_info.method = "GET";
2857 request_info.url = GURL("https://www.google.com");
2858
2859 Initialize(request_info);
2860
2861 url::SchemeHostPort server(request_info.url);
2862 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
2863 SetAlternativeService(request_info, alternative_service);
2864
2865 request_ =
2866 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2867 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2868 EXPECT_TRUE(job_controller_->main_job());
2869 EXPECT_TRUE(job_controller_->alternative_job());
2870
2871 if (alt_job_retried_on_non_default_network) {
2872 // Set the alt job as if it failed on the default network and is retired on
2873 // the alternate network.
2874 JobControllerPeer::SetAltJobFailedOnDefaultNetwork(job_controller_);
2875 }
2876 // Make |alternative_job| succeed.
2877 auto http_stream = std::make_unique<HttpBasicStream>(
2878 std::make_unique<ClientSocketHandle>(), false);
2879 if (async_quic_session) {
2880 base::RunLoop run_loop;
2881 EXPECT_CALL(*job_factory_.main_job(), Resume())
2882 .Times(1)
2883 .WillOnce([&run_loop, this]() {
2884 run_loop.Quit();
2885 job_factory_.main_job()->DoResume();
2886 });
2887 run_loop.Run();
2888 }
2889 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, http_stream.get()));
2890
2891 HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(),
2892 std::move(http_stream));
2893 job_controller_->OnStreamReady(job_factory_.alternative_job());
2894
2895 // Run message loop to make the main job fail.
2896 base::RunLoop().RunUntilIdle();
2897 VerifyBrokenAlternateProtocolMapping(request_info, false);
2898 request_.reset();
2899 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2900 }
2901
2902 // This test verifies that the alternative service is not marked broken if the
2903 // main job fails after the alternative job succeeded on the default network.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobFailsAfterAltJobSucceededOnDefaultNetwork)2904 TEST_P(HttpStreamFactoryJobControllerTest,
2905 MainJobFailsAfterAltJobSucceededOnDefaultNetwork) {
2906 TestMainJobFailsAfterAltJobSucceeded(false, false);
2907 }
2908
2909 // This test verifies that the alternative service is not marked broken if the
2910 // main job fails after the alternative job succeeded on the non-default
2911 // network, i.e., failed on the default network previously.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobFailsAfterAltJobSucceededOnAlternateNetwork)2912 TEST_P(HttpStreamFactoryJobControllerTest,
2913 MainJobFailsAfterAltJobSucceededOnAlternateNetwork) {
2914 TestMainJobFailsAfterAltJobSucceeded(true, false);
2915 }
2916
2917 // This test verifies that the alternative service is not marked broken if the
2918 // main job fails after the alternative job succeeded on the default network.
2919 // This test uses asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobFailsAfterAltJobSucceededOnDefaultNetworkAsyncQuicSession)2920 TEST_P(HttpStreamFactoryJobControllerTest,
2921 MainJobFailsAfterAltJobSucceededOnDefaultNetworkAsyncQuicSession) {
2922 TestMainJobFailsAfterAltJobSucceeded(false, true);
2923 }
2924
2925 // This test verifies that the alternative service is not marked broken if the
2926 // main job fails after the alternative job succeeded on the non-default
2927 // network, i.e., failed on the default network previously. This test uses
2928 // asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobFailsAfterAltJobSucceededOnAlternateNetworkAsyncQuicSession)2929 TEST_P(HttpStreamFactoryJobControllerTest,
2930 MainJobFailsAfterAltJobSucceededOnAlternateNetworkAsyncQuicSession) {
2931 TestMainJobFailsAfterAltJobSucceeded(true, true);
2932 }
2933
2934 void HttpStreamFactoryJobControllerTestBase::
TestMainJobSucceedsAfterAltJobFailed(bool alt_job_retried_on_non_default_network,bool async_quic_session)2935 TestMainJobSucceedsAfterAltJobFailed(
2936 bool alt_job_retried_on_non_default_network,
2937 bool async_quic_session) {
2938 SetAsyncQuicSession(async_quic_session);
2939 quic_data_ = std::make_unique<MockQuicData>(version_);
2940 quic_data_->AddConnect(SYNCHRONOUS, ERR_FAILED);
2941
2942 tcp_data_ = std::make_unique<SequencedSocketData>();
2943 tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
2944 SSLSocketDataProvider ssl_data(ASYNC, OK);
2945 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
2946
2947 base::HistogramTester histogram_tester;
2948 HttpRequestInfo request_info;
2949 request_info.method = "GET";
2950 request_info.url = GURL("https://www.google.com");
2951
2952 Initialize(request_info);
2953
2954 url::SchemeHostPort server(request_info.url);
2955 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
2956 SetAlternativeService(request_info, alternative_service);
2957
2958 request_ =
2959 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
2960 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
2961 EXPECT_TRUE(job_controller_->main_job());
2962 EXPECT_TRUE(job_controller_->alternative_job());
2963
2964 // |alternative_job| fails but should not report status to Request.
2965 EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _, _)).Times(0);
2966 if (async_quic_session) {
2967 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() {
2968 job_factory_.main_job()->DoResume();
2969 });
2970 }
2971 // |main_job| succeeds and should report status to Request.
2972 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _));
2973
2974 if (alt_job_retried_on_non_default_network) {
2975 // Set the alt job as if it failed on the default network and is retired on
2976 // the alternate network.
2977 JobControllerPeer::SetAltJobFailedOnDefaultNetwork(job_controller_);
2978 }
2979
2980 base::RunLoop().RunUntilIdle();
2981
2982 request_.reset();
2983 // Verify that the alternate protocol is marked as broken.
2984 VerifyBrokenAlternateProtocolMapping(request_info, true);
2985 histogram_tester.ExpectUniqueSample("Net.AlternateServiceFailed", -ERR_FAILED,
2986 1);
2987 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
2988 // Verify the brokenness is not cleared when the default network changes.
2989 session_->http_server_properties()->OnDefaultNetworkChanged();
2990 VerifyBrokenAlternateProtocolMapping(request_info, true);
2991 }
2992
2993 // This test verifies that the alternative service will be marked broken when
2994 // the alternative job fails on the default network and main job succeeds later.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterAltJobFailedOnDefaultNetwork)2995 TEST_P(HttpStreamFactoryJobControllerTest,
2996 MainJobSucceedsAfterAltJobFailedOnDefaultNetwork) {
2997 TestMainJobSucceedsAfterAltJobFailed(false, false);
2998 }
2999
3000 // This test verifies that the alternative service will be marked broken when
3001 // the alternative job fails on both default and alternate networks and main job
3002 // succeeds later.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterAltJobFailedOnBothNetworks)3003 TEST_P(HttpStreamFactoryJobControllerTest,
3004 MainJobSucceedsAfterAltJobFailedOnBothNetworks) {
3005 TestMainJobSucceedsAfterAltJobFailed(true, false);
3006 }
3007
3008 // This test verifies that the alternative service will be marked broken when
3009 // the alternative job fails on the default network and main job succeeds later.
3010 // This test uses asynchronous Quic session creation.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterAltJobFailedOnDefaultNetworkAsyncQuicSession)3011 TEST_P(HttpStreamFactoryJobControllerTest,
3012 MainJobSucceedsAfterAltJobFailedOnDefaultNetworkAsyncQuicSession) {
3013 TestMainJobSucceedsAfterAltJobFailed(false, true);
3014 }
3015
3016 // This test verifies that the alternative service will be marked broken when
3017 // the alternative job fails on both default and alternate networks and main job
3018 // succeeds later. This test uses asynchronous Quic session creation.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterAltJobFailedOnBothNetworksAsyncQuicSession)3019 TEST_P(HttpStreamFactoryJobControllerTest,
3020 MainJobSucceedsAfterAltJobFailedOnBothNetworksAsyncQuicSession) {
3021 TestMainJobSucceedsAfterAltJobFailed(true, true);
3022 }
3023
3024 void HttpStreamFactoryJobControllerTestBase::
TestMainJobSucceedsAfterIgnoredError(int net_error,bool async_quic_session,bool expect_broken,std::string alternate_host)3025 TestMainJobSucceedsAfterIgnoredError(int net_error,
3026 bool async_quic_session,
3027 bool expect_broken,
3028 std::string alternate_host) {
3029 SetAsyncQuicSession(async_quic_session);
3030 quic_data_ = std::make_unique<MockQuicData>(version_);
3031 quic_data_->AddConnect(SYNCHRONOUS, net_error);
3032 tcp_data_ = std::make_unique<SequencedSocketData>();
3033 tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
3034 SSLSocketDataProvider ssl_data(ASYNC, OK);
3035 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
3036
3037 base::HistogramTester histogram_tester;
3038
3039 HttpRequestInfo request_info;
3040 request_info.method = "GET";
3041 request_info.url = GURL("https://www.google.com");
3042 Initialize(request_info);
3043
3044 url::SchemeHostPort server(request_info.url);
3045 if (alternate_host.empty()) {
3046 alternate_host = server.host();
3047 }
3048 AlternativeService alternative_service(kProtoQUIC, alternate_host, 443);
3049 SetAlternativeService(request_info, alternative_service);
3050
3051 request_ =
3052 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
3053 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
3054 EXPECT_TRUE(job_controller_->main_job());
3055 EXPECT_TRUE(job_controller_->alternative_job());
3056
3057 // |alternative_job| fails but should not report status to Request.
3058 EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _, _)).Times(0);
3059 if (async_quic_session) {
3060 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() {
3061 job_factory_.main_job()->DoResume();
3062 });
3063 }
3064 // |main_job| succeeds and should report status to Request.
3065 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _));
3066 base::RunLoop().RunUntilIdle();
3067 request_.reset();
3068
3069 // Verify that the alternate protocol is not marked as broken.
3070 VerifyBrokenAlternateProtocolMapping(request_info, expect_broken);
3071 if (expect_broken) {
3072 histogram_tester.ExpectUniqueSample("Net.AlternateServiceFailed",
3073 -net_error, 1);
3074 }
3075 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
3076 }
3077
3078 // Verifies that if the alternative job fails due to a connection change event,
3079 // then the alternative service is not marked as broken.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterConnectionChanged)3080 TEST_P(HttpStreamFactoryJobControllerTest,
3081 MainJobSucceedsAfterConnectionChanged) {
3082 TestMainJobSucceedsAfterIgnoredError(ERR_NETWORK_CHANGED, false);
3083 }
3084
3085 // Verifies that if the alternative job fails due to a disconnected network,
3086 // then the alternative service is not marked as broken.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterInternetDisconnected)3087 TEST_P(HttpStreamFactoryJobControllerTest,
3088 MainJobSucceedsAfterInternetDisconnected) {
3089 TestMainJobSucceedsAfterIgnoredError(ERR_INTERNET_DISCONNECTED, false);
3090 }
3091
3092 // Verifies that if the alternative job fails due to a connection change event,
3093 // then the alternative service is not marked as broken. This test uses
3094 // asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterConnectionChangedAsyncQuicSession)3095 TEST_P(HttpStreamFactoryJobControllerTest,
3096 MainJobSucceedsAfterConnectionChangedAsyncQuicSession) {
3097 TestMainJobSucceedsAfterIgnoredError(ERR_NETWORK_CHANGED, true);
3098 }
3099
3100 // Verifies that if the alternative job fails due to a disconnected network,
3101 // then the alternative service is not marked as broken. This test uses
3102 // asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterInternetDisconnectedAsyncQuicSession)3103 TEST_P(HttpStreamFactoryJobControllerTest,
3104 MainJobSucceedsAfterInternetDisconnectedAsyncQuicSession) {
3105 TestMainJobSucceedsAfterIgnoredError(ERR_INTERNET_DISCONNECTED, true);
3106 }
3107
3108 // Verifies that if the alternative job fails due to a DNS failure,
3109 // then the alternative service is not marked as broken.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterDnsFailure)3110 TEST_P(HttpStreamFactoryJobControllerTest, MainJobSucceedsAfterDnsFailure) {
3111 TestMainJobSucceedsAfterIgnoredError(ERR_NAME_NOT_RESOLVED, false);
3112 }
3113
3114 // Verifies that if the alternative job fails due to a DNS failure,
3115 // then the alternative service is not marked as broken. This test uses
3116 // asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterDnsFailureAsyncQuicSession)3117 TEST_P(HttpStreamFactoryJobControllerTest,
3118 MainJobSucceedsAfterDnsFailureAsyncQuicSession) {
3119 TestMainJobSucceedsAfterIgnoredError(ERR_NAME_NOT_RESOLVED, true);
3120 }
3121
3122 // Verifies that if the alternative job fails due to a DNS failure on a
3123 // different name, then the alternative service is marked as broken.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterDnsFailureWithAlternateName)3124 TEST_P(HttpStreamFactoryJobControllerTest,
3125 MainJobSucceedsAfterDnsFailureWithAlternateName) {
3126 TestMainJobSucceedsAfterIgnoredError(ERR_NAME_NOT_RESOLVED, false, true,
3127 "alternate.google.com");
3128 }
3129
3130 // Verifies that if the alternative job fails due to a DNS failure on a
3131 // different name, then the alternative service is marked as broken. This test
3132 // uses asynchronous QUIC session creation.
TEST_P(HttpStreamFactoryJobControllerTest,MainJobSucceedsAfterDnsFailureWithAlternateNameAsyncQuicSession)3133 TEST_P(HttpStreamFactoryJobControllerTest,
3134 MainJobSucceedsAfterDnsFailureWithAlternateNameAsyncQuicSession) {
3135 TestMainJobSucceedsAfterIgnoredError(ERR_NAME_NOT_RESOLVED, true, true,
3136 "alternate.google.com");
3137 }
3138
3139 // Regression test for crbug/621069.
3140 // Get load state after main job fails and before alternative job succeeds.
TEST_P(HttpStreamFactoryJobControllerTest,GetLoadStateAfterMainJobFailed)3141 TEST_P(HttpStreamFactoryJobControllerTest, GetLoadStateAfterMainJobFailed) {
3142 // Use COLD_START to complete alt job manually.
3143 quic_data_ = std::make_unique<MockQuicData>(version_);
3144 quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
3145 crypto_client_stream_factory_.set_handshake_mode(
3146 MockCryptoClientStream::COLD_START);
3147
3148 tcp_data_ = std::make_unique<SequencedSocketData>();
3149 tcp_data_->set_connect_data(MockConnect(ASYNC, ERR_FAILED));
3150
3151 HttpRequestInfo request_info;
3152 request_info.method = "GET";
3153 request_info.url = GURL("https://www.google.com");
3154
3155 Initialize(request_info);
3156 url::SchemeHostPort server(request_info.url);
3157 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
3158 SetAlternativeService(request_info, alternative_service);
3159
3160 request_ =
3161 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
3162 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
3163 EXPECT_TRUE(job_controller_->main_job());
3164 EXPECT_TRUE(job_controller_->alternative_job());
3165
3166 // |main_job| fails but should not report status to Request.
3167 // The alternative job will mark the main job complete.
3168 EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _, _)).Times(0);
3169
3170 base::RunLoop().RunUntilIdle();
3171
3172 // Controller should use alternative job to get load state.
3173 job_controller_->GetLoadState();
3174
3175 // |alternative_job| succeeds and should report status to Request.
3176 auto http_stream = std::make_unique<HttpBasicStream>(
3177 std::make_unique<ClientSocketHandle>(), false);
3178 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, http_stream.get()));
3179
3180 HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(),
3181 std::move(http_stream));
3182 job_controller_->OnStreamReady(job_factory_.alternative_job());
3183
3184 request_.reset();
3185 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
3186 }
3187
TestResumeMainJobWhenAltJobStalls(bool async_quic_session)3188 void HttpStreamFactoryJobControllerTestBase::TestResumeMainJobWhenAltJobStalls(
3189 bool async_quic_session) {
3190 SetAsyncQuicSession(async_quic_session);
3191 // Use COLD_START to stall alt job.
3192 quic_data_ = std::make_unique<MockQuicData>(version_);
3193 quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
3194 crypto_client_stream_factory_.set_handshake_mode(
3195 MockCryptoClientStream::COLD_START);
3196
3197 tcp_data_ = std::make_unique<SequencedSocketData>();
3198 tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
3199 SSLSocketDataProvider ssl_data(ASYNC, OK);
3200 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
3201
3202 HttpRequestInfo request_info;
3203 request_info.method = "GET";
3204 request_info.url = GURL("https://www.google.com");
3205
3206 Initialize(request_info);
3207 url::SchemeHostPort server(request_info.url);
3208 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
3209 SetAlternativeService(request_info, alternative_service);
3210
3211 request_ =
3212 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
3213 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
3214 EXPECT_TRUE(job_controller_->main_job());
3215 EXPECT_TRUE(job_controller_->alternative_job());
3216 if (async_quic_session) {
3217 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() {
3218 job_factory_.main_job()->DoResume();
3219 });
3220 }
3221 // Alt job is stalled and main job should complete successfully.
3222 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _));
3223
3224 base::RunLoop().RunUntilIdle();
3225 }
3226
TEST_P(HttpStreamFactoryJobControllerTest,ResumeMainJobWhenAltJobStalls)3227 TEST_P(HttpStreamFactoryJobControllerTest, ResumeMainJobWhenAltJobStalls) {
3228 TestResumeMainJobWhenAltJobStalls(false);
3229 }
3230
TEST_P(HttpStreamFactoryJobControllerTest,ResumeMainJobWhenAltJobStallsAsyncQuicSession)3231 TEST_P(HttpStreamFactoryJobControllerTest,
3232 ResumeMainJobWhenAltJobStallsAsyncQuicSession) {
3233 TestResumeMainJobWhenAltJobStalls(true);
3234 }
3235
TEST_P(HttpStreamFactoryJobControllerTest,InvalidPortForQuic)3236 TEST_P(HttpStreamFactoryJobControllerTest, InvalidPortForQuic) {
3237 HttpRequestInfo request_info;
3238 request_info.method = "GET";
3239 request_info.url = GURL("https://www.google.com");
3240
3241 // Using a restricted port 101 for QUIC should fail and the alternative job
3242 // should post OnStreamFailedCall on the controller to resume the main job.
3243 Initialize(request_info);
3244
3245 url::SchemeHostPort server(request_info.url);
3246 AlternativeService alternative_service(kProtoQUIC, server.host(), 101);
3247 SetAlternativeService(request_info, alternative_service);
3248
3249 request_ =
3250 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
3251 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
3252
3253 EXPECT_TRUE(job_factory_.main_job()->is_waiting());
3254
3255 // Wait until OnStreamFailedCallback is executed on the alternative job.
3256 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1);
3257 base::RunLoop().RunUntilIdle();
3258 }
3259
3260 // Verifies that the main job is not resumed until after the alt job completes
3261 // host resolution.
TEST_P(HttpStreamFactoryJobControllerTest,HostResolutionHang)3262 TEST_P(HttpStreamFactoryJobControllerTest, HostResolutionHang) {
3263 auto hanging_resolver = std::make_unique<MockHostResolver>();
3264 hanging_resolver->set_ondemand_mode(true);
3265 hanging_resolver->rules()->AddRule("www.google.com", "1.2.3.4");
3266 session_deps_.host_resolver = std::move(hanging_resolver);
3267
3268 HttpRequestInfo request_info;
3269 request_info.method = "GET";
3270 request_info.url = GURL("https://www.google.com");
3271
3272 Initialize(request_info);
3273
3274 // handshake will fail asynchronously after mock data is unpaused.
3275 MockQuicData quic_data(version_);
3276 quic_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause
3277 quic_data.AddRead(ASYNC, ERR_FAILED);
3278 quic_data.AddWrite(ASYNC, ERR_FAILED);
3279 quic_data.AddSocketDataToFactory(session_deps_.socket_factory.get());
3280
3281 // Enable delayed TCP and set time delay for waiting job.
3282 QuicSessionPool* quic_session_pool = session_->quic_session_pool();
3283 quic_session_pool->set_is_quic_known_to_work_on_current_network(true);
3284 ServerNetworkStats stats1;
3285 stats1.srtt = base::Microseconds(10);
3286 session_->http_server_properties()->SetServerNetworkStats(
3287 url::SchemeHostPort(GURL("https://www.google.com")),
3288 NetworkAnonymizationKey(), stats1);
3289
3290 url::SchemeHostPort server(request_info.url);
3291 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
3292 SetAlternativeService(request_info, alternative_service);
3293
3294 // This prevents handshake from immediately succeeding.
3295 crypto_client_stream_factory_.set_handshake_mode(
3296 MockCryptoClientStream::COLD_START);
3297
3298 request_ =
3299 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
3300 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
3301
3302 EXPECT_TRUE(job_controller_->main_job());
3303 EXPECT_TRUE(job_controller_->alternative_job());
3304 EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_));
3305
3306 // Since the alt job has not finished host resolution, there should be no
3307 // delayed task posted to resume the main job.
3308 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
3309 FastForwardBy(base::Microseconds(50));
3310 EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_));
3311
3312 // Allow alt job host resolution to complete.
3313 session_deps_.host_resolver->ResolveAllPending();
3314
3315 // Task to resume main job in 15 microseconds should be posted.
3316 EXPECT_NE(0u, GetPendingMainThreadTaskCount());
3317 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
3318 FastForwardBy(base::Microseconds(14));
3319 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1);
3320 FastForwardBy(base::Microseconds(1));
3321
3322 EXPECT_TRUE(job_controller_->main_job());
3323 EXPECT_TRUE(job_controller_->alternative_job());
3324
3325 // Unpause mock quic data.
3326 // Will cause |alternative_job| to fail, but its failure should not be
3327 // reported to Request.
3328 EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _, _)).Times(0);
3329 EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
3330 EXPECT_TRUE(JobControllerPeer::main_job_is_resumed(job_controller_));
3331 // OnStreamFailed will post a task to resume the main job immediately but
3332 // won't call Resume() on the main job since it's been resumed already.
3333 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
3334 quic_data.Resume();
3335 FastForwardUntilNoTasksRemain();
3336 // Alt job should be cleaned up
3337 EXPECT_FALSE(job_controller_->alternative_job());
3338 }
3339
3340 // Regression test for crbug.com/789560.
TEST_P(HttpStreamFactoryJobControllerTest,ResumeMainJobLaterCanceled)3341 TEST_P(HttpStreamFactoryJobControllerTest, ResumeMainJobLaterCanceled) {
3342 std::unique_ptr<ConfiguredProxyResolutionService> proxy_resolution_service =
3343 ConfiguredProxyResolutionService::CreateDirect();
3344 ConfiguredProxyResolutionService* proxy_resolution_service_raw =
3345 proxy_resolution_service.get();
3346 session_deps_.proxy_resolution_service = std::move(proxy_resolution_service);
3347
3348 // Using hanging resolver will cause the alternative job to hang indefinitely.
3349 session_deps_.alternate_host_resolver =
3350 std::make_unique<HangingHostResolver>();
3351
3352 HttpRequestInfo request_info;
3353 request_info.method = "GET";
3354 request_info.url = GURL("https://www.google.com");
3355
3356 Initialize(request_info);
3357
3358 // Enable delayed TCP and set time delay for waiting job.
3359 QuicSessionPool* quic_session_pool = session_->quic_session_pool();
3360 quic_session_pool->set_is_quic_known_to_work_on_current_network(true);
3361 ServerNetworkStats stats1;
3362 stats1.srtt = base::Microseconds(10);
3363 session_->http_server_properties()->SetServerNetworkStats(
3364 url::SchemeHostPort(GURL("https://www.google.com")),
3365 NetworkAnonymizationKey(), stats1);
3366
3367 url::SchemeHostPort server(request_info.url);
3368 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
3369 SetAlternativeService(request_info, alternative_service);
3370
3371 request_ =
3372 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
3373 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
3374 EXPECT_TRUE(job_controller_->main_job());
3375 EXPECT_TRUE(job_controller_->alternative_job());
3376 EXPECT_TRUE(job_controller_->main_job()->is_waiting());
3377
3378 base::RunLoop run_loop;
3379 // The main job should be resumed without delay when alt job fails.
3380 EXPECT_CALL(*job_factory_.main_job(), Resume())
3381 .Times(1)
3382 .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); }));
3383 job_controller_->OnStreamFailed(job_factory_.alternative_job(),
3384 ERR_QUIC_PROTOCOL_ERROR);
3385 FastForwardBy(base::Microseconds(0));
3386 run_loop.Run();
3387 EXPECT_FALSE(job_controller_->alternative_job());
3388
3389 // Calling ForceReloadProxyConfig will cause the proxy configuration to
3390 // change. It will still be the direct connection but the configuration
3391 // version will be bumped. That is enough for the job controller to restart
3392 // the jobs.
3393 proxy_resolution_service_raw->ForceReloadProxyConfig();
3394 HttpStreamFactoryJobPeer::SetShouldReconsiderProxy(job_factory_.main_job());
3395 // Now the alt service is marked as broken (e.g. through a different request),
3396 // so only non-alt job is restarted.
3397 session_->http_server_properties()->MarkAlternativeServiceBroken(
3398 alternative_service, NetworkAnonymizationKey());
3399
3400 job_controller_->OnStreamFailed(job_factory_.main_job(), ERR_FAILED);
3401 // Jobs are restarted.
3402 EXPECT_TRUE(job_controller_->main_job());
3403 EXPECT_FALSE(job_controller_->alternative_job());
3404
3405 // There shouldn't be any ResumeMainJobLater() delayed tasks.
3406 // This EXPECT_CALL will fail before crbug.com/789560 fix.
3407 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
3408 FastForwardBy(base::Microseconds(15));
3409
3410 EXPECT_TRUE(job_controller_->main_job());
3411 request_.reset();
3412 }
3413
3414 // Test that main job is blocked for kMaxDelayTimeForMainJob(3s) if
3415 // http_server_properties cached an inappropriate large srtt for the server,
3416 // which would potentially delay the main job for a extremely long time in
3417 // delayed tcp case.
TEST_P(HttpStreamFactoryJobControllerTest,DelayedTCPWithLargeSrtt)3418 TEST_P(HttpStreamFactoryJobControllerTest, DelayedTCPWithLargeSrtt) {
3419 // The max delay time should be in sync with .cc file.
3420 base::TimeDelta kMaxDelayTimeForMainJob = base::Seconds(3);
3421
3422 HttpRequestInfo request_info;
3423 request_info.method = "GET";
3424 request_info.url = GURL("https://www.google.com");
3425
3426 Initialize(request_info);
3427
3428 // handshake will fail asynchronously after mock data is unpaused.
3429 MockQuicData quic_data(version_);
3430 quic_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause
3431 quic_data.AddRead(ASYNC, ERR_FAILED);
3432 quic_data.AddWrite(ASYNC, ERR_FAILED);
3433 quic_data.AddSocketDataToFactory(session_deps_.socket_factory.get());
3434
3435 // Enable delayed TCP and set time delay for waiting job.
3436 QuicSessionPool* quic_session_pool = session_->quic_session_pool();
3437 quic_session_pool->set_is_quic_known_to_work_on_current_network(true);
3438 ServerNetworkStats stats1;
3439 stats1.srtt = base::Seconds(100);
3440 session_->http_server_properties()->SetServerNetworkStats(
3441 url::SchemeHostPort(GURL("https://www.google.com")),
3442 NetworkAnonymizationKey(), stats1);
3443
3444 url::SchemeHostPort server(request_info.url);
3445 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
3446 SetAlternativeService(request_info, alternative_service);
3447
3448 // This prevents handshake from immediately succeeding.
3449 crypto_client_stream_factory_.set_handshake_mode(
3450 MockCryptoClientStream::COLD_START);
3451
3452 request_ =
3453 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
3454 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
3455
3456 EXPECT_TRUE(job_controller_->main_job());
3457 EXPECT_TRUE(job_controller_->alternative_job());
3458 base::RunLoop().RunUntilIdle();
3459 // Main job is not blocked but hasn't resumed yet; it should resume in 3s.
3460 EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
3461 EXPECT_FALSE(JobControllerPeer::main_job_is_resumed(job_controller_));
3462
3463 // Task to resume main job in 3 seconds should be posted.
3464 EXPECT_NE(0u, GetPendingMainThreadTaskCount());
3465 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
3466 FastForwardBy(kMaxDelayTimeForMainJob - base::Microseconds(1));
3467 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1);
3468 FastForwardBy(base::Microseconds(1));
3469
3470 EXPECT_TRUE(job_controller_->main_job());
3471 EXPECT_TRUE(job_controller_->alternative_job());
3472 EXPECT_TRUE(JobControllerPeer::main_job_is_resumed(job_controller_));
3473
3474 // Unpause mock quic data and run all remaining tasks. Alt-job should fail
3475 // and be cleaned up.
3476 quic_data.Resume();
3477 FastForwardUntilNoTasksRemain();
3478 EXPECT_FALSE(job_controller_->alternative_job());
3479 }
3480
3481 // TODO(https://crbug.com/1007502): Disabled because the pending task count does
3482 // not match expectations.
TEST_P(HttpStreamFactoryJobControllerTest,DISABLED_ResumeMainJobImmediatelyOnStreamFailed)3483 TEST_P(HttpStreamFactoryJobControllerTest,
3484 DISABLED_ResumeMainJobImmediatelyOnStreamFailed) {
3485 HttpRequestInfo request_info;
3486 request_info.method = "GET";
3487 request_info.url = GURL("https://www.google.com");
3488
3489 Initialize(request_info);
3490
3491 // handshake will fail asynchronously after mock data is unpaused.
3492 MockQuicData quic_data(version_);
3493 quic_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause
3494 quic_data.AddRead(ASYNC, ERR_FAILED);
3495 quic_data.AddWrite(ASYNC, ERR_FAILED);
3496 quic_data.AddSocketDataToFactory(session_deps_.socket_factory.get());
3497
3498 // Enable delayed TCP and set time delay for waiting job.
3499 QuicSessionPool* quic_session_pool = session_->quic_session_pool();
3500 quic_session_pool->set_is_quic_known_to_work_on_current_network(true);
3501 ServerNetworkStats stats1;
3502 stats1.srtt = base::Microseconds(10);
3503 session_->http_server_properties()->SetServerNetworkStats(
3504 url::SchemeHostPort(GURL("https://www.google.com")),
3505 NetworkAnonymizationKey(), stats1);
3506
3507 url::SchemeHostPort server(request_info.url);
3508 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
3509 SetAlternativeService(request_info, alternative_service);
3510
3511 // This prevents handshake from immediately succeeding.
3512 crypto_client_stream_factory_.set_handshake_mode(
3513 MockCryptoClientStream::COLD_START);
3514
3515 request_ =
3516 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
3517 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
3518
3519 EXPECT_TRUE(job_controller_->main_job());
3520 EXPECT_TRUE(job_controller_->alternative_job());
3521 // Main job is not blocked but hasn't resumed yet; it's scheduled to resume
3522 // in 15us.
3523 EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
3524 EXPECT_FALSE(JobControllerPeer::main_job_is_resumed(job_controller_));
3525
3526 // Task to resume main job in 15us should be posted.
3527 EXPECT_NE(0u, GetPendingMainThreadTaskCount());
3528
3529 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
3530 FastForwardBy(base::Microseconds(1));
3531
3532 // Now unpause the mock quic data to fail the alt job. This should immediately
3533 // resume the main job.
3534 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1);
3535 quic_data.Resume();
3536 FastForwardBy(base::TimeDelta());
3537
3538 EXPECT_TRUE(job_controller_->main_job());
3539 EXPECT_FALSE(job_controller_->alternative_job());
3540 EXPECT_TRUE(JobControllerPeer::main_job_is_resumed(job_controller_));
3541
3542 // Verify there is another task to resume main job with delay but should
3543 // not call Resume() on the main job as main job has been resumed.
3544 EXPECT_NE(0u, GetPendingMainThreadTaskCount());
3545 EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
3546 FastForwardBy(base::Microseconds(15));
3547
3548 FastForwardUntilNoTasksRemain();
3549 }
3550
TEST_P(HttpStreamFactoryJobControllerTest,PreconnectToHostWithValidAltSvc)3551 TEST_P(HttpStreamFactoryJobControllerTest, PreconnectToHostWithValidAltSvc) {
3552 quic_data_ = std::make_unique<MockQuicData>(version_);
3553 quic_data_->AddWrite(SYNCHRONOUS, client_maker_.MakeInitialSettingsPacket(1));
3554 quic_data_->AddRead(ASYNC, ERR_CONNECTION_CLOSED);
3555
3556 HttpRequestInfo request_info;
3557 request_info.method = "GET";
3558 request_info.url = GURL("https://www.example.com");
3559 SetPreconnect();
3560
3561 Initialize(request_info);
3562
3563 url::SchemeHostPort server(request_info.url);
3564 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
3565 SetAlternativeService(request_info, alternative_service);
3566
3567 job_controller_->Preconnect(1);
3568 EXPECT_TRUE(job_controller_->main_job());
3569 EXPECT_EQ(HttpStreamFactory::PRECONNECT,
3570 job_controller_->main_job()->job_type());
3571 EXPECT_FALSE(job_controller_->alternative_job());
3572
3573 base::RunLoop().RunUntilIdle();
3574 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
3575 }
3576
3577 // When preconnect to a H2 supported server, only 1 connection is opened.
TEST_P(HttpStreamFactoryJobControllerTest,PreconnectMultipleStreamsToH2Server)3578 TEST_P(HttpStreamFactoryJobControllerTest,
3579 PreconnectMultipleStreamsToH2Server) {
3580 tcp_data_ = std::make_unique<SequencedSocketData>();
3581 tcp_data_->set_connect_data(MockConnect(ASYNC, OK));
3582 SetPreconnect();
3583
3584 HttpRequestInfo request_info;
3585 request_info.method = "GET";
3586 request_info.url = GURL("http://www.example.com");
3587 Initialize(request_info);
3588
3589 // Sets server support HTTP/2.
3590 url::SchemeHostPort server(request_info.url);
3591 session_->http_server_properties()->SetSupportsSpdy(
3592 server, NetworkAnonymizationKey(), true);
3593
3594 job_controller_->Preconnect(/*num_streams=*/5);
3595 // Only one job is started.
3596 EXPECT_TRUE(job_controller_->main_job());
3597 EXPECT_FALSE(job_controller_->alternative_job());
3598 EXPECT_EQ(HttpStreamFactory::PRECONNECT,
3599 job_controller_->main_job()->job_type());
3600 // There is only 1 connect even though multiple streams were requested.
3601 EXPECT_EQ(
3602 1, HttpStreamFactoryJobPeer::GetNumStreams(job_controller_->main_job()));
3603
3604 base::RunLoop().RunUntilIdle();
3605 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
3606 }
3607
3608 // Check that the logic to only preconnect a single socket to servers with H2
3609 // support respects NetworkIsolationKeys.
TEST_P(HttpStreamFactoryJobControllerTest,PreconnectMultipleStreamsToH2ServerWithNetworkIsolationKey)3610 TEST_P(HttpStreamFactoryJobControllerTest,
3611 PreconnectMultipleStreamsToH2ServerWithNetworkIsolationKey) {
3612 base::test::ScopedFeatureList feature_list;
3613 // It's not strictly necessary to enable
3614 // |kPartitionConnectionsByNetworkIsolationKey|, but the second phase of the
3615 // test would only make 4 connections, reusing the first connection, without
3616 // it.
3617 feature_list.InitWithFeatures(
3618 {// enabled_features
3619 features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
3620 features::kPartitionConnectionsByNetworkIsolationKey},
3621 // disabled_features
3622 {});
3623 // Need to re-create HttpServerProperties after enabling the field trial,
3624 // since it caches the field trial value on construction.
3625 session_deps_.http_server_properties =
3626 std::make_unique<HttpServerProperties>();
3627
3628 const SchemefulSite kSite1(GURL("https://foo.test/"));
3629 const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
3630 const auto kNetworkAnonymizationKey1 =
3631 NetworkAnonymizationKey::CreateSameSite(kSite1);
3632 const SchemefulSite kSite2(GURL("https://bar.test/"));
3633 const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
3634 const auto kNetworkAnonymizationKey2 =
3635 NetworkAnonymizationKey::CreateSameSite(kSite2);
3636
3637 tcp_data_ = std::make_unique<SequencedSocketData>();
3638 tcp_data_->set_connect_data(MockConnect(ASYNC, OK));
3639 SetPreconnect();
3640
3641 HttpRequestInfo request_info;
3642 request_info.method = "GET";
3643 request_info.url = GURL("http://www.example.com");
3644 request_info.network_isolation_key = kNetworkIsolationKey1;
3645 request_info.network_anonymization_key = kNetworkAnonymizationKey1;
3646 Initialize(request_info);
3647
3648 // Sets server support HTTP/2, using kNetworkIsolationKey.
3649 url::SchemeHostPort server(request_info.url);
3650 session_->http_server_properties()->SetSupportsSpdy(
3651 server, kNetworkAnonymizationKey1, true);
3652
3653 job_controller_->Preconnect(/*num_streams=*/5);
3654 // Only one job is started.
3655 EXPECT_TRUE(job_controller_->main_job());
3656 EXPECT_FALSE(job_controller_->alternative_job());
3657 EXPECT_EQ(HttpStreamFactory::PRECONNECT,
3658 job_controller_->main_job()->job_type());
3659 // There is only 1 connect even though multiple streams were requested.
3660 EXPECT_EQ(
3661 1, HttpStreamFactoryJobPeer::GetNumStreams(job_controller_->main_job()));
3662
3663 base::RunLoop().RunUntilIdle();
3664 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
3665
3666 // Now try using two different NetworkIsolationKeys, one empty, one not, and
3667 // make sure that 5 sockets are preconnected with each one.
3668 std::vector<std::unique_ptr<SequencedSocketData>> socket_data;
3669 for (auto other_network_isolation_key :
3670 {NetworkIsolationKey(), kNetworkIsolationKey2}) {
3671 for (int i = 0; i < 5; ++i) {
3672 socket_data.emplace_back(std::make_unique<SequencedSocketData>(
3673 MockConnect(ASYNC, OK), base::span<const MockRead>(),
3674 base::span<const MockWrite>()));
3675 session_deps_.socket_factory->AddSocketDataProvider(
3676 socket_data.back().get());
3677 }
3678
3679 request_info.network_isolation_key = other_network_isolation_key;
3680 request_info.network_anonymization_key =
3681 net::NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
3682 other_network_isolation_key);
3683 MockHttpStreamRequestDelegate request_delegate;
3684 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
3685 factory_, &request_delegate, session_.get(), &job_factory_,
3686 request_info, is_preconnect_, /*is_websocket=*/false,
3687 enable_ip_based_pooling_, enable_alternative_services_,
3688 delay_main_job_with_available_spdy_session_,
3689 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
3690 auto* job_controller_ptr = job_controller.get();
3691 HttpStreamFactoryPeer::AddJobController(factory_,
3692 std::move(job_controller));
3693 job_controller_ptr->Preconnect(/*num_streams=*/5);
3694 // Five jobs should be started.
3695 EXPECT_TRUE(job_controller_ptr->main_job());
3696 EXPECT_FALSE(job_controller_ptr->alternative_job());
3697 EXPECT_EQ(HttpStreamFactory::PRECONNECT,
3698 job_controller_ptr->main_job()->job_type());
3699 EXPECT_EQ(5, HttpStreamFactoryJobPeer::GetNumStreams(
3700 job_controller_ptr->main_job()));
3701
3702 base::RunLoop().RunUntilIdle();
3703 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
3704 }
3705 }
3706
3707 void HttpStreamFactoryJobControllerTestBase::
TestDoNotDelayMainJobIfHasAvailableSpdySession(bool async_quic_session)3708 TestDoNotDelayMainJobIfHasAvailableSpdySession(bool async_quic_session) {
3709 SetAsyncQuicSession(async_quic_session);
3710
3711 SetNotDelayMainJobWithAvailableSpdySession();
3712 HttpRequestInfo request_info;
3713 request_info.method = "GET";
3714 request_info.url = GURL("https://www.google.com");
3715
3716 Initialize(request_info);
3717 // Put a SpdySession in the pool.
3718 HostPortPair host_port_pair("www.google.com", 443);
3719 SpdySessionKey key(host_port_pair, PRIVACY_MODE_DISABLED,
3720 ProxyChain::Direct(), SessionUsage::kDestination,
3721 SocketTag(), NetworkAnonymizationKey(),
3722 SecureDnsPolicy::kAllow,
3723 /*disable_cert_verification_network_fetches=*/false);
3724 std::ignore = CreateFakeSpdySession(session_->spdy_session_pool(), key);
3725
3726 // Handshake will fail asynchronously after mock data is unpaused.
3727 MockQuicData quic_data(version_);
3728 quic_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause
3729 quic_data.AddRead(ASYNC, ERR_FAILED);
3730 quic_data.AddWrite(ASYNC, ERR_FAILED);
3731 quic_data.AddSocketDataToFactory(session_deps_.socket_factory.get());
3732
3733 // Enable delayed TCP and set time delay for waiting job.
3734 QuicSessionPool* quic_session_pool = session_->quic_session_pool();
3735 quic_session_pool->set_is_quic_known_to_work_on_current_network(true);
3736 ServerNetworkStats stats1;
3737 stats1.srtt = base::Milliseconds(100);
3738 session_->http_server_properties()->SetServerNetworkStats(
3739 url::SchemeHostPort(GURL("https://www.google.com")),
3740 NetworkAnonymizationKey(), stats1);
3741
3742 url::SchemeHostPort server(request_info.url);
3743 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
3744 SetAlternativeService(request_info, alternative_service);
3745
3746 // This prevents handshake from immediately succeeding.
3747 crypto_client_stream_factory_.set_handshake_mode(
3748 MockCryptoClientStream::COLD_START);
3749
3750 request_ =
3751 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
3752 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
3753
3754 EXPECT_TRUE(job_controller_->main_job());
3755 EXPECT_TRUE(job_controller_->alternative_job());
3756 // The main job shouldn't have any delay since request can be sent on
3757 // available SPDY session. When QUIC session creation is async, the main job
3758 // should still be blocked as alt job has not succeeded or failed at least
3759 // once yet. Otherwise the main job should not be blocked
3760 EXPECT_EQ(job_controller_->get_main_job_wait_time_for_tests(),
3761 base::TimeDelta());
3762 if (async_quic_session) {
3763 EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_));
3764 // The main job should have a SPDY session available.
3765 EXPECT_TRUE(job_controller_->main_job()->HasAvailableSpdySession());
3766 // Wait for QUIC session creation attempt to resume and unblock the main
3767 // job.
3768 FastForwardBy(base::Milliseconds(1));
3769 // Main job should still have no delay and should be unblocked now.
3770 EXPECT_EQ(job_controller_->get_main_job_wait_time_for_tests(),
3771 base::TimeDelta());
3772 EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
3773 } else {
3774 EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
3775 EXPECT_TRUE(job_controller_->main_job()->HasAvailableSpdySession());
3776 }
3777 }
3778
TEST_P(HttpStreamFactoryJobControllerTest,DoNotDelayMainJobIfHasAvailableSpdySession)3779 TEST_P(HttpStreamFactoryJobControllerTest,
3780 DoNotDelayMainJobIfHasAvailableSpdySession) {
3781 TestDoNotDelayMainJobIfHasAvailableSpdySession(false);
3782 }
3783
TEST_P(HttpStreamFactoryJobControllerTest,DoNotDelayMainJobIfHasAvailableSpdySessionAsyncQuicSession)3784 TEST_P(HttpStreamFactoryJobControllerTest,
3785 DoNotDelayMainJobIfHasAvailableSpdySessionAsyncQuicSession) {
3786 TestDoNotDelayMainJobIfHasAvailableSpdySession(true);
3787 }
3788
3789 // Check the case that while a preconnect is waiting in the H2 request queue,
3790 // and a SPDY session appears, the job completes successfully.
TEST_P(HttpStreamFactoryJobControllerTest,SpdySessionInterruptsPreconnect)3791 TEST_P(HttpStreamFactoryJobControllerTest, SpdySessionInterruptsPreconnect) {
3792 // Make sure there is only one socket connect.
3793 MockWrite writes[] = {MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 0)};
3794 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 1)};
3795 tcp_data_ = std::make_unique<SequencedSocketData>(reads, writes);
3796 // connect needs to be async, so the H2 session isn't created immediately.
3797 tcp_data_->set_connect_data(MockConnect(ASYNC, OK));
3798 SSLSocketDataProvider ssl_data(ASYNC, OK);
3799 ssl_data.next_proto = kProtoHTTP2;
3800 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
3801 HttpRequestInfo request_info;
3802 request_info.method = "GET";
3803 request_info.url = GURL("https://www.example.com");
3804 Initialize(request_info);
3805
3806 // Sets server support HTTP/2.
3807 url::SchemeHostPort server(request_info.url);
3808 session_->http_server_properties()->SetSupportsSpdy(
3809 server, NetworkAnonymizationKey(), true);
3810
3811 // Start a non-preconnect request.
3812 std::unique_ptr<HttpStreamRequest> stream_request = job_controller_->Start(
3813 &request_delegate_, nullptr /* websocket_handshake_create_helper */,
3814 NetLogWithSource(), HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
3815 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _));
3816
3817 // Create and start a preconnect request, which should start watching the
3818 // SpdySessionPool.
3819 MockHttpStreamRequestDelegate preconnect_request_delegate;
3820 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
3821 factory_, &preconnect_request_delegate, session_.get(), &job_factory_,
3822 request_info, /*is_preconnect=*/true, /*is_websocket=*/false,
3823 enable_ip_based_pooling_, enable_alternative_services_,
3824 delay_main_job_with_available_spdy_session_,
3825 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
3826 auto* job_controller_ptr = job_controller.get();
3827 HttpStreamFactoryPeer::AddJobController(factory_, std::move(job_controller));
3828 job_controller_ptr->Preconnect(1);
3829 EXPECT_TRUE(job_controller_ptr->main_job());
3830 EXPECT_FALSE(job_controller_ptr->alternative_job());
3831
3832 // The non-preconnect request should create an H2 session, which the
3833 // preconnect then sees, and the preconnect request should complete and be
3834 // torn down without ever requesting a socket. If it did request a socket, the
3835 // test would fail since the mock socket factory would see an unexpected
3836 // socket request.
3837 base::RunLoop().RunUntilIdle();
3838
3839 stream_request.reset();
3840
3841 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
3842
3843 // Sanity check - make sure the SpdySession was created.
3844 base::WeakPtr<SpdySession> spdy_session =
3845 session_->spdy_session_pool()->FindAvailableSession(
3846 SpdySessionKey(HostPortPair::FromURL(request_info.url),
3847 request_info.privacy_mode, ProxyChain::Direct(),
3848 SessionUsage::kDestination, request_info.socket_tag,
3849 request_info.network_anonymization_key,
3850 request_info.secure_dns_policy,
3851 /*disable_cert_verification_network_fetches=*/false),
3852 false /* enable_ip_based_pooling */, /*is_websocket=*/false,
3853 NetLogWithSource());
3854 EXPECT_TRUE(spdy_session);
3855 }
3856
3857 // This test verifies that a preconnect job doesn't block subsequent requests
3858 // which can use an existing IP based pooled SpdySession.
3859 // This test uses "wildcard.pem" to support IpBasedPooling for *.example.org,
3860 // and starts 3 requests:
3861 // [1] Normal non-preconnect request to www.example.org.
3862 // [2] Preconnect request to other.example.org. The connection is paused until
3863 // OnConnectComplete() is called in the end of the test.
3864 // [3] Normal non-preconnect request to other.example.org. This request must
3865 // succeed even while the preconnect request [2] is paused.
TEST_P(HttpStreamFactoryJobControllerTest,PreconnectJobDoesntBlockIpBasedPooling)3866 TEST_P(HttpStreamFactoryJobControllerTest,
3867 PreconnectJobDoesntBlockIpBasedPooling) {
3868 // Make sure that both "www.example.org" and "other.example.org" are pointing
3869 // to the same IP address.
3870 session_deps_.host_resolver->rules()->AddRule(
3871 "www.example.org", IPAddress::IPv4Localhost().ToString());
3872 session_deps_.host_resolver->rules()->AddRule(
3873 "other.example.org", IPAddress::IPv4Localhost().ToString());
3874 // Make |host_resolver| asynchronous to simulate the issue of
3875 // crbug.com/1320608.
3876 session_deps_.host_resolver->set_synchronous_mode(false);
3877
3878 // This is used for the non-preconnect requests [1] and [3].
3879 MockWrite writes[] = {MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 0)};
3880 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 1)};
3881 SequencedSocketData first_socket(reads, writes);
3882 first_socket.set_connect_data(MockConnect(ASYNC, OK));
3883 session_deps_.socket_factory->AddSocketDataProvider(&first_socket);
3884
3885 // This is used for the non-preconnect requests.
3886 SSLSocketDataProvider ssl_data1(ASYNC, OK);
3887 ssl_data1.next_proto = kProtoHTTP2;
3888 // "wildcard.pem" supports "*.example.org".
3889 ssl_data1.ssl_info.cert =
3890 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
3891 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
3892
3893 // This is used for the preconnect request.
3894 SequencedSocketData second_socket;
3895 // The connection is paused. And it will be completed with
3896 // ERR_CONNECTION_FAILED.
3897 second_socket.set_connect_data(MockConnect(ASYNC, ERR_IO_PENDING));
3898 session_deps_.socket_factory->AddSocketDataProvider(&second_socket);
3899
3900 HttpRequestInfo request_info;
3901 request_info.method = "GET";
3902 request_info.url = GURL("https://www.example.org");
3903 Initialize(request_info);
3904
3905 // Start a non-preconnect request [1].
3906 {
3907 std::unique_ptr<HttpStreamRequest> stream_request = job_controller_->Start(
3908 &request_delegate_,
3909 /*websocket_handshake_stream_create_helper=*/nullptr,
3910 NetLogWithSource(), HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
3911 if (dns_https_alpn_enabled()) {
3912 EXPECT_CALL(*job_factory_.main_job(), Resume())
3913 .Times(1)
3914 .WillOnce([this]() { job_factory_.main_job()->DoResume(); });
3915 }
3916 base::RunLoop run_loop;
3917 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
3918 .WillOnce([&run_loop]() { run_loop.Quit(); });
3919 run_loop.Run();
3920 }
3921
3922 // Sanity check - make sure the SpdySession was created.
3923 {
3924 base::WeakPtr<SpdySession> spdy_session =
3925 session_->spdy_session_pool()->FindAvailableSession(
3926 SpdySessionKey(HostPortPair::FromURL(request_info.url),
3927 request_info.privacy_mode, ProxyChain::Direct(),
3928 SessionUsage::kDestination, request_info.socket_tag,
3929 request_info.network_anonymization_key,
3930 request_info.secure_dns_policy,
3931 /*disable_cert_verification_network_fetches=*/false),
3932 /*enable_ip_based_pooling=*/false, /*is_websocket=*/false,
3933 NetLogWithSource());
3934 EXPECT_TRUE(spdy_session);
3935 }
3936
3937 HttpRequestInfo other_request_info;
3938 other_request_info.method = "GET";
3939 other_request_info.url = GURL("https://other.example.org");
3940
3941 // Create and start a preconnect request [2].
3942 MockHttpStreamRequestDelegate preconnect_request_delegate;
3943 auto preconnect_job_controller =
3944 std::make_unique<HttpStreamFactory::JobController>(
3945 factory_, &preconnect_request_delegate, session_.get(), &job_factory_,
3946 other_request_info, /*is_preconnect=*/true,
3947 /*is_websocket=*/false, /*enable_ip_based_pooling=*/true,
3948 enable_alternative_services_,
3949 delay_main_job_with_available_spdy_session_,
3950 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
3951 auto* preconnect_job_controller_ptr = preconnect_job_controller.get();
3952 HttpStreamFactoryPeer::AddJobController(factory_,
3953 std::move(preconnect_job_controller));
3954 preconnect_job_controller_ptr->Preconnect(1);
3955 base::RunLoop().RunUntilIdle();
3956
3957 // The SpdySession is available for IP based pooling when the host resolution
3958 // has finished.
3959 {
3960 const SpdySessionKey spdy_session_key = SpdySessionKey(
3961 HostPortPair::FromURL(other_request_info.url),
3962 other_request_info.privacy_mode, ProxyChain::Direct(),
3963 SessionUsage::kDestination, other_request_info.socket_tag,
3964 other_request_info.network_anonymization_key,
3965 other_request_info.secure_dns_policy,
3966 /*disable_cert_verification_network_fetches=*/false);
3967 EXPECT_FALSE(session_->spdy_session_pool()->FindAvailableSession(
3968 spdy_session_key, /*enable_ip_based_pooling=*/false,
3969 /*is_websocket=*/false, NetLogWithSource()));
3970 EXPECT_TRUE(session_->spdy_session_pool()->FindAvailableSession(
3971 spdy_session_key, /*enable_ip_based_pooling=*/true,
3972 /*is_websocket=*/false, NetLogWithSource()));
3973 }
3974
3975 // Create and start a second non-preconnect request [3].
3976 {
3977 MockHttpStreamRequestDelegate request_delegate;
3978 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
3979 factory_, &request_delegate, session_.get(), &job_factory_,
3980 other_request_info, /*is_preconnect=*/false,
3981 /*is_websocket=*/false, /*enable_ip_based_pooling=*/true,
3982 enable_alternative_services_,
3983 delay_main_job_with_available_spdy_session_,
3984 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
3985 auto* job_controller_ptr = job_controller.get();
3986 HttpStreamFactoryPeer::AddJobController(factory_,
3987 std::move(job_controller));
3988 std::unique_ptr<HttpStreamRequest> second_stream_request =
3989 job_controller_ptr->Start(
3990 &request_delegate,
3991 /*websocket_handshake_stream_create_helper=*/nullptr,
3992 NetLogWithSource(), HttpStreamRequest::HTTP_STREAM,
3993 DEFAULT_PRIORITY);
3994
3995 base::RunLoop run_loop;
3996 EXPECT_CALL(request_delegate, OnStreamReadyImpl(_, _))
3997 .WillOnce([&run_loop]() { run_loop.Quit(); });
3998 run_loop.Run();
3999 second_stream_request.reset();
4000 }
4001
4002 second_socket.socket()->OnConnectComplete(
4003 MockConnect(SYNCHRONOUS, ERR_CONNECTION_FAILED));
4004 base::RunLoop().RunUntilIdle();
4005
4006 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
4007 EXPECT_TRUE(first_socket.AllReadDataConsumed());
4008 EXPECT_TRUE(first_socket.AllWriteDataConsumed());
4009 }
4010
4011 class JobControllerLimitMultipleH2Requests
4012 : public HttpStreamFactoryJobControllerTestBase {
4013 protected:
JobControllerLimitMultipleH2Requests()4014 JobControllerLimitMultipleH2Requests()
4015 : HttpStreamFactoryJobControllerTestBase(false) {}
4016 const int kNumRequests = 5;
SetUp()4017 void SetUp() override { SkipCreatingJobController(); }
4018 };
4019
TEST_F(JobControllerLimitMultipleH2Requests,MultipleRequests)4020 TEST_F(JobControllerLimitMultipleH2Requests, MultipleRequests) {
4021 // Make sure there is only one socket connect.
4022 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
4023 tcp_data_ =
4024 std::make_unique<SequencedSocketData>(reads, base::span<MockWrite>());
4025 tcp_data_->set_connect_data(MockConnect(ASYNC, OK));
4026 SSLSocketDataProvider ssl_data(ASYNC, OK);
4027 ssl_data.next_proto = kProtoHTTP2;
4028 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
4029 HttpRequestInfo request_info;
4030 request_info.method = "GET";
4031 request_info.url = GURL("https://www.example.com");
4032 Initialize(request_info);
4033 SpdySessionPoolPeer pool_peer(session_->spdy_session_pool());
4034 pool_peer.SetEnableSendingInitialData(false);
4035
4036 // Sets server support HTTP/2.
4037 url::SchemeHostPort server(request_info.url);
4038 session_->http_server_properties()->SetSupportsSpdy(
4039 server, NetworkAnonymizationKey(), true);
4040
4041 std::vector<std::unique_ptr<MockHttpStreamRequestDelegate>> request_delegates;
4042 std::vector<std::unique_ptr<HttpStreamRequest>> requests;
4043 for (int i = 0; i < kNumRequests; ++i) {
4044 request_delegates.emplace_back(
4045 std::make_unique<MockHttpStreamRequestDelegate>());
4046 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
4047 factory_, request_delegates[i].get(), session_.get(), &job_factory_,
4048 request_info, is_preconnect_, /*is_websocket=*/false,
4049 enable_ip_based_pooling_, enable_alternative_services_,
4050 delay_main_job_with_available_spdy_session_,
4051 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
4052 auto* job_controller_ptr = job_controller.get();
4053 HttpStreamFactoryPeer::AddJobController(factory_,
4054 std::move(job_controller));
4055 auto request = job_controller_ptr->Start(
4056 request_delegates[i].get(), nullptr, net_log_with_source_,
4057 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
4058 EXPECT_TRUE(job_controller_ptr->main_job());
4059 EXPECT_FALSE(job_controller_ptr->alternative_job());
4060 requests.push_back(std::move(request));
4061 }
4062
4063 for (int i = 0; i < kNumRequests; ++i) {
4064 EXPECT_CALL(*request_delegates[i].get(), OnStreamReadyImpl(_, _));
4065 }
4066
4067 base::RunLoop().RunUntilIdle();
4068 requests.clear();
4069 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
4070 auto entries = net_log_observer_.GetEntries();
4071 size_t log_position = 0;
4072 for (int i = 0; i < kNumRequests - 1; ++i) {
4073 log_position = ExpectLogContainsSomewhereAfter(
4074 entries, log_position, NetLogEventType::HTTP_STREAM_JOB_THROTTLED,
4075 NetLogEventPhase::NONE);
4076 }
4077 }
4078
4079 // Check that throttling simultaneous requests to a single H2 server respects
4080 // NetworkIsolationKeys.
TEST_F(JobControllerLimitMultipleH2Requests,MultipleRequestsNetworkIsolationKey)4081 TEST_F(JobControllerLimitMultipleH2Requests,
4082 MultipleRequestsNetworkIsolationKey) {
4083 base::test::ScopedFeatureList feature_list;
4084 feature_list.InitWithFeatures(
4085 {// enabled_features
4086 features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
4087 features::kPartitionConnectionsByNetworkIsolationKey},
4088 // disabled_features
4089 {});
4090 // Need to re-create HttpServerProperties after enabling the field trial,
4091 // since it caches the field trial value on construction.
4092 session_deps_.http_server_properties =
4093 std::make_unique<HttpServerProperties>();
4094
4095 const SchemefulSite kSite1(GURL("https://foo.test/"));
4096 const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
4097 const auto kNetworkAnonymizationKey1 =
4098 NetworkAnonymizationKey::CreateSameSite(kSite1);
4099 const SchemefulSite kSite2(GURL("https://bar.test/"));
4100 const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
4101 const auto kNetworkAnonymizationKey2 =
4102 NetworkAnonymizationKey::CreateSameSite(kSite2);
4103
4104 tcp_data_ = std::make_unique<SequencedSocketData>(
4105 MockConnect(SYNCHRONOUS, ERR_IO_PENDING), base::span<MockRead>(),
4106 base::span<MockWrite>());
4107 HttpRequestInfo request_info;
4108 request_info.method = "GET";
4109 request_info.url = GURL("https://www.example.com");
4110 Initialize(request_info);
4111
4112 // Sets server support HTTP/2.
4113 url::SchemeHostPort server(request_info.url);
4114 session_->http_server_properties()->SetSupportsSpdy(
4115 server, kNetworkAnonymizationKey1, true);
4116
4117 std::vector<std::unique_ptr<MockHttpStreamRequestDelegate>> request_delegates;
4118 std::vector<std::unique_ptr<HttpStreamRequest>> requests;
4119 std::vector<std::unique_ptr<SequencedSocketData>> socket_data;
4120 for (int i = 0; i < kNumRequests; ++i) {
4121 // Shouldn't matter whether requests are interleaved by NetworkIsolationKey
4122 // or not.
4123 for (const auto& network_isolation_key :
4124 {NetworkIsolationKey(), kNetworkIsolationKey1,
4125 kNetworkIsolationKey2}) {
4126 request_info.network_isolation_key = network_isolation_key;
4127 request_info.network_anonymization_key =
4128 net::NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
4129 network_isolation_key);
4130 // For kNetworkIsolationKey1, all requests but the first will be
4131 // throttled.
4132 if (i == 0 || network_isolation_key != kNetworkIsolationKey1) {
4133 socket_data.emplace_back(std::make_unique<SequencedSocketData>(
4134 MockConnect(ASYNC, OK), base::span<const MockRead>(),
4135 base::span<const MockWrite>()));
4136 session_deps_.socket_factory->AddSocketDataProvider(
4137 socket_data.back().get());
4138 }
4139 request_delegates.emplace_back(
4140 std::make_unique<MockHttpStreamRequestDelegate>());
4141 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
4142 factory_, request_delegates[i].get(), session_.get(), &job_factory_,
4143 request_info, is_preconnect_, /*is_websocket=*/false,
4144 enable_ip_based_pooling_, enable_alternative_services_,
4145 delay_main_job_with_available_spdy_session_,
4146 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
4147 auto* job_controller_ptr = job_controller.get();
4148 HttpStreamFactoryPeer::AddJobController(factory_,
4149 std::move(job_controller));
4150 auto request = job_controller_ptr->Start(
4151 request_delegates[i].get(), nullptr, net_log_with_source_,
4152 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
4153 EXPECT_TRUE(job_controller_ptr->main_job());
4154 EXPECT_FALSE(job_controller_ptr->alternative_job());
4155 requests.push_back(std::move(request));
4156 }
4157 }
4158 TransportClientSocketPool* socket_pool =
4159 reinterpret_cast<TransportClientSocketPool*>(session_->GetSocketPool(
4160 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct()));
4161 ClientSocketPool::GroupId group_id0(
4162 url::SchemeHostPort(request_info.url), request_info.privacy_mode,
4163 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
4164 /*disable_cert_network_fetches=*/false);
4165 ClientSocketPool::GroupId group_id1(
4166 url::SchemeHostPort(request_info.url), request_info.privacy_mode,
4167 kNetworkAnonymizationKey1, SecureDnsPolicy::kAllow,
4168 /*disable_cert_network_fetches=*/false);
4169 ClientSocketPool::GroupId group_id2(
4170 url::SchemeHostPort(request_info.url), request_info.privacy_mode,
4171 kNetworkAnonymizationKey2, SecureDnsPolicy::kAllow,
4172 /*disable_cert_network_fetches=*/false);
4173 EXPECT_EQ(static_cast<uint32_t>(kNumRequests),
4174 socket_pool->NumConnectJobsInGroupForTesting(group_id0));
4175 EXPECT_EQ(1u, socket_pool->NumConnectJobsInGroupForTesting(group_id1));
4176 EXPECT_EQ(static_cast<uint32_t>(kNumRequests),
4177 socket_pool->NumConnectJobsInGroupForTesting(group_id2));
4178 }
4179
TEST_F(JobControllerLimitMultipleH2Requests,MultipleRequestsFirstRequestHang)4180 TEST_F(JobControllerLimitMultipleH2Requests, MultipleRequestsFirstRequestHang) {
4181 // First socket connect hang.
4182 SequencedSocketData hangdata;
4183 hangdata.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
4184 session_deps_.socket_factory->AddSocketDataProvider(&hangdata);
4185 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
4186 std::list<SequencedSocketData> socket_data;
4187 std::list<SSLSocketDataProvider> ssl_socket_data;
4188 // kNumRequests - 1 will resume themselves after a delay. There will be
4189 // kNumRequests - 1 sockets opened.
4190 for (int i = 0; i < kNumRequests - 1; i++) {
4191 // Only the first one needs a MockRead because subsequent sockets are
4192 // not used to establish a SpdySession.
4193 if (i == 0) {
4194 socket_data.emplace_back(reads, base::span<MockWrite>());
4195 } else {
4196 socket_data.emplace_back();
4197 }
4198 socket_data.back().set_connect_data(MockConnect(ASYNC, OK));
4199 session_deps_.socket_factory->AddSocketDataProvider(&socket_data.back());
4200 ssl_socket_data.emplace_back(ASYNC, OK);
4201 ssl_socket_data.back().next_proto = kProtoHTTP2;
4202 session_deps_.socket_factory->AddSSLSocketDataProvider(
4203 &ssl_socket_data.back());
4204 }
4205 HttpRequestInfo request_info;
4206 request_info.method = "GET";
4207 request_info.url = GURL("https://www.example.com");
4208 Initialize(request_info);
4209 SpdySessionPoolPeer pool_peer(session_->spdy_session_pool());
4210 pool_peer.SetEnableSendingInitialData(false);
4211
4212 // Sets server support HTTP/2.
4213 url::SchemeHostPort server(request_info.url);
4214 session_->http_server_properties()->SetSupportsSpdy(
4215 server, NetworkAnonymizationKey(), true);
4216
4217 std::vector<std::unique_ptr<MockHttpStreamRequestDelegate>> request_delegates;
4218 std::vector<std::unique_ptr<HttpStreamRequest>> requests;
4219 for (int i = 0; i < kNumRequests; ++i) {
4220 request_delegates.push_back(
4221 std::make_unique<MockHttpStreamRequestDelegate>());
4222 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
4223 factory_, request_delegates[i].get(), session_.get(), &job_factory_,
4224 request_info, is_preconnect_, /*is_websocket=*/false,
4225 enable_ip_based_pooling_, enable_alternative_services_,
4226 delay_main_job_with_available_spdy_session_,
4227 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
4228 auto* job_controller_ptr = job_controller.get();
4229 HttpStreamFactoryPeer::AddJobController(factory_,
4230 std::move(job_controller));
4231 auto request = job_controller_ptr->Start(
4232 request_delegates[i].get(), nullptr, net_log_with_source_,
4233 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
4234 EXPECT_TRUE(job_controller_ptr->main_job());
4235 EXPECT_FALSE(job_controller_ptr->alternative_job());
4236 requests.push_back(std::move(request));
4237 }
4238
4239 for (int i = 0; i < kNumRequests; ++i) {
4240 EXPECT_CALL(*request_delegates[i].get(), OnStreamReadyImpl(_, _));
4241 }
4242
4243 EXPECT_GT(GetPendingMainThreadTaskCount(), 0u);
4244 FastForwardBy(base::Milliseconds(HttpStreamFactory::Job::kHTTP2ThrottleMs));
4245 base::RunLoop().RunUntilIdle();
4246
4247 EXPECT_FALSE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
4248 requests.clear();
4249 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
4250
4251 EXPECT_TRUE(hangdata.AllReadDataConsumed());
4252 for (const auto& data : socket_data) {
4253 EXPECT_TRUE(data.AllReadDataConsumed());
4254 EXPECT_TRUE(data.AllWriteDataConsumed());
4255 }
4256 }
4257
TEST_F(JobControllerLimitMultipleH2Requests,MultipleRequestsFirstRequestCanceled)4258 TEST_F(JobControllerLimitMultipleH2Requests,
4259 MultipleRequestsFirstRequestCanceled) {
4260 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
4261 SequencedSocketData first_socket(reads, base::span<MockWrite>());
4262 first_socket.set_connect_data(MockConnect(ASYNC, OK));
4263 SSLSocketDataProvider first_ssl_data(ASYNC, OK);
4264 first_ssl_data.next_proto = kProtoHTTP2;
4265 session_deps_.socket_factory->AddSocketDataProvider(&first_socket);
4266 session_deps_.socket_factory->AddSSLSocketDataProvider(&first_ssl_data);
4267 std::list<SequencedSocketData> socket_data;
4268 std::list<SSLSocketDataProvider> ssl_socket_data;
4269 // kNumRequests - 1 will be resumed when the first request is canceled.
4270 for (int i = 0; i < kNumRequests - 1; i++) {
4271 socket_data.emplace_back();
4272 socket_data.back().set_connect_data(MockConnect(ASYNC, OK));
4273 session_deps_.socket_factory->AddSocketDataProvider(&socket_data.back());
4274 ssl_socket_data.emplace_back(ASYNC, OK);
4275 ssl_socket_data.back().next_proto = kProtoHTTP2;
4276 session_deps_.socket_factory->AddSSLSocketDataProvider(
4277 &ssl_socket_data.back());
4278 }
4279
4280 HttpRequestInfo request_info;
4281 request_info.method = "GET";
4282 request_info.url = GURL("https://www.example.com");
4283 Initialize(request_info);
4284 SpdySessionPoolPeer pool_peer(session_->spdy_session_pool());
4285 pool_peer.SetEnableSendingInitialData(false);
4286
4287 // Sets server support HTTP/2.
4288 url::SchemeHostPort server(request_info.url);
4289 session_->http_server_properties()->SetSupportsSpdy(
4290 server, NetworkAnonymizationKey(), true);
4291
4292 std::vector<std::unique_ptr<MockHttpStreamRequestDelegate>> request_delegates;
4293 std::vector<std::unique_ptr<HttpStreamRequest>> requests;
4294 for (int i = 0; i < kNumRequests; ++i) {
4295 request_delegates.emplace_back(
4296 std::make_unique<MockHttpStreamRequestDelegate>());
4297 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
4298 factory_, request_delegates[i].get(), session_.get(), &job_factory_,
4299 request_info, is_preconnect_, /*is_websocket=*/false,
4300 enable_ip_based_pooling_, enable_alternative_services_,
4301 delay_main_job_with_available_spdy_session_,
4302 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
4303 auto* job_controller_ptr = job_controller.get();
4304 HttpStreamFactoryPeer::AddJobController(factory_,
4305 std::move(job_controller));
4306 auto request = job_controller_ptr->Start(
4307 request_delegates[i].get(), nullptr, net_log_with_source_,
4308 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
4309 EXPECT_TRUE(job_controller_ptr->main_job());
4310 EXPECT_FALSE(job_controller_ptr->alternative_job());
4311 requests.push_back(std::move(request));
4312 }
4313 // Cancel the first one.
4314 requests[0].reset();
4315
4316 for (int i = 1; i < kNumRequests; ++i) {
4317 EXPECT_CALL(*request_delegates[i].get(), OnStreamReadyImpl(_, _));
4318 }
4319 base::RunLoop().RunUntilIdle();
4320
4321 EXPECT_FALSE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
4322 requests.clear();
4323 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
4324
4325 EXPECT_TRUE(first_socket.AllReadDataConsumed());
4326 for (const auto& data : socket_data) {
4327 EXPECT_TRUE(data.AllReadDataConsumed());
4328 EXPECT_TRUE(data.AllWriteDataConsumed());
4329 }
4330 }
4331
TEST_F(JobControllerLimitMultipleH2Requests,MultiplePreconnects)4332 TEST_F(JobControllerLimitMultipleH2Requests, MultiplePreconnects) {
4333 // Make sure there is only one socket connect.
4334 tcp_data_ = std::make_unique<SequencedSocketData>();
4335 tcp_data_->set_connect_data(MockConnect(ASYNC, OK));
4336 SSLSocketDataProvider ssl_data(ASYNC, OK);
4337 ssl_data.next_proto = kProtoHTTP2;
4338 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
4339 HttpRequestInfo request_info;
4340 request_info.method = "GET";
4341 request_info.url = GURL("https://www.example.com");
4342 SetPreconnect();
4343 Initialize(request_info);
4344
4345 // Sets server support HTTP/2.
4346 url::SchemeHostPort server(request_info.url);
4347 session_->http_server_properties()->SetSupportsSpdy(
4348 server, NetworkAnonymizationKey(), true);
4349
4350 std::vector<std::unique_ptr<MockHttpStreamRequestDelegate>> request_delegates;
4351 for (int i = 0; i < kNumRequests; ++i) {
4352 request_delegates.emplace_back(
4353 std::make_unique<MockHttpStreamRequestDelegate>());
4354 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
4355 factory_, request_delegates[i].get(), session_.get(), &job_factory_,
4356 request_info, is_preconnect_, /*is_websocket=*/false,
4357 enable_ip_based_pooling_, enable_alternative_services_,
4358 delay_main_job_with_available_spdy_session_,
4359 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
4360 auto* job_controller_ptr = job_controller.get();
4361 HttpStreamFactoryPeer::AddJobController(factory_,
4362 std::move(job_controller));
4363 job_controller_ptr->Preconnect(1);
4364 EXPECT_TRUE(job_controller_ptr->main_job());
4365 EXPECT_FALSE(job_controller_ptr->alternative_job());
4366 }
4367 base::RunLoop().RunUntilIdle();
4368 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
4369 }
4370
TEST_F(JobControllerLimitMultipleH2Requests,H1NegotiatedForFirstRequest)4371 TEST_F(JobControllerLimitMultipleH2Requests, H1NegotiatedForFirstRequest) {
4372 // First socket is an HTTP/1.1 socket.
4373 SequencedSocketData first_socket;
4374 first_socket.set_connect_data(MockConnect(ASYNC, OK));
4375 SSLSocketDataProvider ssl_data(ASYNC, OK);
4376 session_deps_.socket_factory->AddSocketDataProvider(&first_socket);
4377 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
4378 // Second socket is an HTTP/2 socket.
4379 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
4380 SequencedSocketData second_socket(reads, base::span<MockWrite>());
4381 second_socket.set_connect_data(MockConnect(ASYNC, OK));
4382 session_deps_.socket_factory->AddSocketDataProvider(&second_socket);
4383 SSLSocketDataProvider second_ssl_data(ASYNC, OK);
4384 second_ssl_data.next_proto = kProtoHTTP2;
4385 session_deps_.socket_factory->AddSSLSocketDataProvider(&second_ssl_data);
4386
4387 HttpRequestInfo request_info;
4388 request_info.method = "GET";
4389 request_info.url = GURL("https://www.example.com");
4390 Initialize(request_info);
4391 SpdySessionPoolPeer pool_peer(session_->spdy_session_pool());
4392 pool_peer.SetEnableSendingInitialData(false);
4393
4394 // Sets server support HTTP/2.
4395 url::SchemeHostPort server(request_info.url);
4396 session_->http_server_properties()->SetSupportsSpdy(
4397 server, NetworkAnonymizationKey(), true);
4398
4399 std::vector<std::unique_ptr<MockHttpStreamRequestDelegate>> request_delegates;
4400 std::vector<std::unique_ptr<HttpStreamRequest>> requests;
4401 for (int i = 0; i < 2; ++i) {
4402 request_delegates.emplace_back(
4403 std::make_unique<MockHttpStreamRequestDelegate>());
4404 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
4405 factory_, request_delegates[i].get(), session_.get(), &job_factory_,
4406 request_info, is_preconnect_, /*is_websocket=*/false,
4407 enable_ip_based_pooling_, enable_alternative_services_,
4408 delay_main_job_with_available_spdy_session_,
4409 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
4410 auto* job_controller_ptr = job_controller.get();
4411 HttpStreamFactoryPeer::AddJobController(factory_,
4412 std::move(job_controller));
4413 auto request = job_controller_ptr->Start(
4414 request_delegates[i].get(), nullptr, net_log_with_source_,
4415 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
4416 EXPECT_TRUE(job_controller_ptr->main_job());
4417 EXPECT_FALSE(job_controller_ptr->alternative_job());
4418 requests.push_back(std::move(request));
4419 }
4420
4421 for (int i = 0; i < 2; ++i) {
4422 EXPECT_CALL(*request_delegates[i].get(), OnStreamReadyImpl(_, _));
4423 }
4424 base::RunLoop().RunUntilIdle();
4425
4426 EXPECT_FALSE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
4427 requests.clear();
4428 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
4429
4430 EXPECT_TRUE(first_socket.AllReadDataConsumed());
4431 EXPECT_FALSE(second_socket.AllReadDataConsumed());
4432 }
4433
4434 // Tests that HTTP/2 throttling logic only applies to non-QUIC jobs.
TEST_F(JobControllerLimitMultipleH2Requests,QuicJobNotThrottled)4435 TEST_F(JobControllerLimitMultipleH2Requests, QuicJobNotThrottled) {
4436 crypto_client_stream_factory_.set_handshake_mode(
4437 MockCryptoClientStream::COLD_START);
4438 quic_data_ = std::make_unique<MockQuicData>(version_);
4439 quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
4440 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
4441 tcp_data_ =
4442 std::make_unique<SequencedSocketData>(reads, base::span<MockWrite>());
4443
4444 tcp_data_->set_connect_data(MockConnect(ASYNC, OK));
4445 SSLSocketDataProvider ssl_data(ASYNC, OK);
4446 ssl_data.next_proto = kProtoHTTP2;
4447 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
4448
4449 HttpRequestInfo request_info;
4450 request_info.method = "GET";
4451 request_info.url = GURL("https://www.google.com");
4452
4453 Initialize(request_info);
4454 SpdySessionPoolPeer pool_peer(session_->spdy_session_pool());
4455 pool_peer.SetEnableSendingInitialData(false);
4456
4457 url::SchemeHostPort server(request_info.url);
4458 // Sets server supports QUIC.
4459 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
4460 SetAlternativeService(request_info, alternative_service);
4461
4462 // Sets server support HTTP/2.
4463 session_->http_server_properties()->SetSupportsSpdy(
4464 server, NetworkAnonymizationKey(), true);
4465
4466 // Use default job factory so that Resume() is not mocked out.
4467 HttpStreamFactory::JobFactory default_job_factory;
4468 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
4469 factory_, &request_delegate_, session_.get(), &default_job_factory,
4470 request_info, is_preconnect_, /*is_websocket=*/false,
4471 enable_ip_based_pooling_, enable_alternative_services_,
4472 delay_main_job_with_available_spdy_session_,
4473 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
4474 auto* job_controller_ptr = job_controller.get();
4475 HttpStreamFactoryPeer::AddJobController(factory_, std::move(job_controller));
4476 request_ = job_controller_ptr->Start(
4477 &request_delegate_, nullptr, net_log_with_source_,
4478 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
4479
4480 EXPECT_TRUE(job_controller_ptr->main_job());
4481 EXPECT_TRUE(job_controller_ptr->alternative_job());
4482 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _));
4483 base::RunLoop().RunUntilIdle();
4484 auto entries = net_log_observer_.GetEntries();
4485 for (const auto& entry : entries) {
4486 ASSERT_NE(NetLogEventType::HTTP_STREAM_JOB_THROTTLED, entry.type);
4487 }
4488 }
4489
4490 class HttpStreamFactoryJobControllerMisdirectedRequestRetry
4491 : public HttpStreamFactoryJobControllerTestBase,
4492 public ::testing::WithParamInterface<::testing::tuple<bool, bool>> {
4493 public:
HttpStreamFactoryJobControllerMisdirectedRequestRetry()4494 HttpStreamFactoryJobControllerMisdirectedRequestRetry()
4495 : HttpStreamFactoryJobControllerTestBase(false) {}
4496 };
4497
4498 INSTANTIATE_TEST_SUITE_P(All,
4499 HttpStreamFactoryJobControllerMisdirectedRequestRetry,
4500 ::testing::Combine(::testing::Bool(),
4501 ::testing::Bool()));
4502
TEST_P(HttpStreamFactoryJobControllerMisdirectedRequestRetry,DisableIPBasedPoolingAndAlternativeServices)4503 TEST_P(HttpStreamFactoryJobControllerMisdirectedRequestRetry,
4504 DisableIPBasedPoolingAndAlternativeServices) {
4505 const bool enable_ip_based_pooling = ::testing::get<0>(GetParam());
4506 const bool enable_alternative_services = ::testing::get<1>(GetParam());
4507 if (enable_alternative_services) {
4508 quic_data_ = std::make_unique<MockQuicData>(version_);
4509 quic_data_->AddConnect(SYNCHRONOUS, OK);
4510 quic_data_->AddWrite(SYNCHRONOUS,
4511 client_maker_.MakeInitialSettingsPacket(1));
4512 quic_data_->AddRead(ASYNC, ERR_CONNECTION_CLOSED);
4513 }
4514 tcp_data_ = std::make_unique<SequencedSocketData>();
4515 tcp_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
4516 SSLSocketDataProvider ssl_data(ASYNC, OK);
4517 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
4518
4519 HttpRequestInfo request_info;
4520 request_info.method = "GET";
4521 request_info.url = GURL("https://www.google.com");
4522
4523 if (!enable_ip_based_pooling) {
4524 DisableIPBasedPooling();
4525 }
4526 if (!enable_alternative_services) {
4527 DisableAlternativeServices();
4528 }
4529
4530 Initialize(request_info);
4531
4532 url::SchemeHostPort server(request_info.url);
4533 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
4534 SetAlternativeService(request_info, alternative_service);
4535
4536 request_ =
4537 job_controller_->Start(&request_delegate_, nullptr, net_log_with_source_,
4538 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
4539 EXPECT_TRUE(job_controller_->main_job());
4540 if (enable_alternative_services) {
4541 EXPECT_TRUE(job_controller_->alternative_job());
4542 } else {
4543 EXPECT_FALSE(job_controller_->alternative_job());
4544 }
4545
4546 // |main_job| succeeds and should report status to Request.
4547 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _));
4548 base::RunLoop().RunUntilIdle();
4549 }
4550
4551 class HttpStreamFactoryJobControllerPreconnectTest
4552 : public HttpStreamFactoryJobControllerTestBase,
4553 public ::testing::WithParamInterface<bool> {
4554 protected:
HttpStreamFactoryJobControllerPreconnectTest()4555 HttpStreamFactoryJobControllerPreconnectTest()
4556 : HttpStreamFactoryJobControllerTestBase(false) {}
4557
SetUp()4558 void SetUp() override {
4559 if (!GetParam()) {
4560 scoped_feature_list_.InitFromCommandLine(std::string(),
4561 "LimitEarlyPreconnects");
4562 }
4563 }
4564
Initialize()4565 void Initialize() {
4566 session_deps_.http_server_properties =
4567 std::make_unique<HttpServerProperties>(
4568 std::make_unique<MockPrefDelegate>(), nullptr /* net_log */);
4569 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
4570 factory_ = session_->http_stream_factory();
4571 request_info_.method = "GET";
4572 request_info_.url = GURL("https://www.example.com");
4573 auto job_controller = std::make_unique<HttpStreamFactory::JobController>(
4574 factory_, &request_delegate_, session_.get(), &job_factory_,
4575 request_info_, /* is_preconnect = */ true,
4576 /* is_websocket = */ false,
4577 /* enable_ip_based_pooling = */ true,
4578 /* enable_alternative_services = */ true,
4579 /* delay_main_job_with_available_spdy_session = */ true,
4580 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
4581 job_controller_ = job_controller.get();
4582 HttpStreamFactoryPeer::AddJobController(factory_,
4583 std::move(job_controller));
4584 }
4585
4586 protected:
Preconnect(int num_streams)4587 void Preconnect(int num_streams) {
4588 job_controller_->Preconnect(num_streams);
4589 // Only one job is started.
4590 EXPECT_TRUE(job_controller_->main_job());
4591 EXPECT_FALSE(job_controller_->alternative_job());
4592 }
4593
4594 private:
4595 base::test::ScopedFeatureList scoped_feature_list_;
4596 HttpRequestInfo request_info_;
4597 };
4598
4599 INSTANTIATE_TEST_SUITE_P(All,
4600 HttpStreamFactoryJobControllerPreconnectTest,
4601 ::testing::Bool());
4602
TEST_P(HttpStreamFactoryJobControllerPreconnectTest,LimitEarlyPreconnects)4603 TEST_P(HttpStreamFactoryJobControllerPreconnectTest, LimitEarlyPreconnects) {
4604 std::list<SequencedSocketData> providers;
4605 std::list<SSLSocketDataProvider> ssl_providers;
4606 const int kNumPreconects = 5;
4607 MockRead reads[] = {MockRead(ASYNC, OK)};
4608 // If experiment is not enabled, there are 5 socket connects.
4609 const size_t actual_num_connects = GetParam() ? 1 : kNumPreconects;
4610 for (size_t i = 0; i < actual_num_connects; ++i) {
4611 providers.emplace_back(reads, base::span<MockWrite>());
4612 session_deps_.socket_factory->AddSocketDataProvider(&providers.back());
4613 ssl_providers.emplace_back(ASYNC, OK);
4614 session_deps_.socket_factory->AddSSLSocketDataProvider(
4615 &ssl_providers.back());
4616 }
4617 Initialize();
4618 Preconnect(kNumPreconects);
4619 // If experiment is enabled, only 1 stream is requested.
4620 EXPECT_EQ((int)actual_num_connects, HttpStreamFactoryJobPeer::GetNumStreams(
4621 job_controller_->main_job()));
4622 base::RunLoop().RunUntilIdle();
4623 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
4624 }
4625
4626 // Test that GetAlternativeServiceInfoFor will include a list of advertised
4627 // versions, which contains a version that is supported. Returns an empty list
4628 // if advertised versions are missing in HttpServerProperties.
TEST_P(HttpStreamFactoryJobControllerTest,GetAlternativeServiceInfoFor)4629 TEST_P(HttpStreamFactoryJobControllerTest, GetAlternativeServiceInfoFor) {
4630 HttpRequestInfo request_info;
4631 request_info.method = "GET";
4632 request_info.url = GURL("https://www.google.com");
4633
4634 Initialize(request_info);
4635 url::SchemeHostPort server(request_info.url);
4636 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
4637 base::Time expiration = base::Time::Now() + base::Days(1);
4638
4639 // Set alternative service with no advertised version.
4640 session_->http_server_properties()->SetQuicAlternativeService(
4641 server, NetworkAnonymizationKey(), alternative_service, expiration,
4642 quic::ParsedQuicVersionVector());
4643
4644 // Simulate proxy resolution succeeding, after which
4645 // GetAlternativeServiceInfoFor can be called.
4646 JobControllerPeer::InitializeProxyInfo(job_controller_);
4647
4648 AlternativeServiceInfo alt_svc_info =
4649 JobControllerPeer::GetAlternativeServiceInfoFor(
4650 job_controller_, request_info, &request_delegate_,
4651 HttpStreamRequest::HTTP_STREAM);
4652 // Verify that JobController get an empty list of supported QUIC versions.
4653 EXPECT_TRUE(alt_svc_info.advertised_versions().empty());
4654
4655 // Set alternative service for the same server with the same list of versions
4656 // that is supported.
4657 quic::ParsedQuicVersionVector supported_versions =
4658 quic_context_.params()->supported_versions;
4659 session_->http_server_properties()->SetQuicAlternativeService(
4660 server, NetworkAnonymizationKey(), alternative_service, expiration,
4661 supported_versions);
4662
4663 alt_svc_info = JobControllerPeer::GetAlternativeServiceInfoFor(
4664 job_controller_, request_info, &request_delegate_,
4665 HttpStreamRequest::HTTP_STREAM);
4666 std::sort(
4667 supported_versions.begin(), supported_versions.end(),
4668 [](const quic::ParsedQuicVersion& a, const quic::ParsedQuicVersion& b) {
4669 return a.transport_version < b.transport_version;
4670 });
4671 quic::ParsedQuicVersionVector advertised_versions =
4672 alt_svc_info.advertised_versions();
4673 std::sort(
4674 advertised_versions.begin(), advertised_versions.end(),
4675 [](const quic::ParsedQuicVersion& a, const quic::ParsedQuicVersion& b) {
4676 return a.transport_version < b.transport_version;
4677 });
4678 EXPECT_EQ(supported_versions, advertised_versions);
4679
4680 quic::ParsedQuicVersion unsupported_version_1 =
4681 quic::ParsedQuicVersion::Unsupported();
4682 quic::ParsedQuicVersion unsupported_version_2 =
4683 quic::ParsedQuicVersion::Unsupported();
4684 for (const quic::ParsedQuicVersion& version : quic::AllSupportedVersions()) {
4685 if (base::Contains(supported_versions, version)) {
4686 continue;
4687 }
4688 if (unsupported_version_1 == quic::ParsedQuicVersion::Unsupported()) {
4689 unsupported_version_1 = version;
4690 continue;
4691 }
4692 unsupported_version_2 = version;
4693 break;
4694 }
4695
4696 // Set alternative service for the same server with two QUIC versions:
4697 // - one unsupported version: |unsupported_version_1|,
4698 // - one supported version:
4699 // quic_context_.params()->supported_versions[0].
4700 quic::ParsedQuicVersionVector mixed_quic_versions = {
4701 unsupported_version_1, quic_context_.params()->supported_versions[0]};
4702 session_->http_server_properties()->SetQuicAlternativeService(
4703 server, NetworkAnonymizationKey(), alternative_service, expiration,
4704 mixed_quic_versions);
4705
4706 alt_svc_info = JobControllerPeer::GetAlternativeServiceInfoFor(
4707 job_controller_, request_info, &request_delegate_,
4708 HttpStreamRequest::HTTP_STREAM);
4709 EXPECT_EQ(2u, alt_svc_info.advertised_versions().size());
4710 // Verify that JobController returns the list of versions specified in set.
4711 EXPECT_EQ(mixed_quic_versions, alt_svc_info.advertised_versions());
4712
4713 // Set alternative service for the same server with two unsupported QUIC
4714 // versions: |unsupported_version_1|, |unsupported_version_2|.
4715 session_->http_server_properties()->SetQuicAlternativeService(
4716 server, NetworkAnonymizationKey(), alternative_service, expiration,
4717 {unsupported_version_1, unsupported_version_2});
4718
4719 alt_svc_info = JobControllerPeer::GetAlternativeServiceInfoFor(
4720 job_controller_, request_info, &request_delegate_,
4721 HttpStreamRequest::HTTP_STREAM);
4722 // Verify that JobController returns no valid alternative service.
4723 EXPECT_EQ(kProtoUnknown, alt_svc_info.alternative_service().protocol);
4724 EXPECT_EQ(0u, alt_svc_info.advertised_versions().size());
4725 }
4726
TestAltSvcVersionSelection(const std::string & alt_svc_header,const quic::ParsedQuicVersion & expected_version,const quic::ParsedQuicVersionVector & supported_versions)4727 void HttpStreamFactoryJobControllerTestBase::TestAltSvcVersionSelection(
4728 const std::string& alt_svc_header,
4729 const quic::ParsedQuicVersion& expected_version,
4730 const quic::ParsedQuicVersionVector& supported_versions) {
4731 quic_context_.params()->supported_versions = supported_versions;
4732 HttpRequestInfo request_info;
4733 request_info.method = "GET";
4734 request_info.url = GURL("https://example.com");
4735 NetworkIsolationKey network_isolation_key(
4736 SchemefulSite(GURL("https://example.com")),
4737 SchemefulSite(GURL("https://example.com")));
4738 auto network_anonymization_key = NetworkAnonymizationKey::CreateSameSite(
4739 SchemefulSite(GURL("https://example.com")));
4740 request_info.network_isolation_key = network_isolation_key;
4741 request_info.network_anonymization_key = network_anonymization_key;
4742
4743 Initialize(request_info);
4744 url::SchemeHostPort origin(request_info.url);
4745 auto headers = base::MakeRefCounted<HttpResponseHeaders>("");
4746 headers->AddHeader("alt-svc", alt_svc_header);
4747 session_->http_stream_factory()->ProcessAlternativeServices(
4748 session_.get(), network_anonymization_key, headers.get(), origin);
4749 // Simulate proxy resolution succeeding, after which
4750 // GetAlternativeServiceInfoFor can be called.
4751 JobControllerPeer::InitializeProxyInfo(job_controller_);
4752 AlternativeServiceInfo alt_svc_info =
4753 JobControllerPeer::GetAlternativeServiceInfoFor(
4754 job_controller_, request_info, &request_delegate_,
4755 HttpStreamRequest::HTTP_STREAM);
4756 quic::ParsedQuicVersionVector advertised_versions =
4757 alt_svc_info.advertised_versions();
4758 quic::ParsedQuicVersion selected_version =
4759 JobControllerPeer::SelectQuicVersion(job_controller_,
4760 advertised_versions);
4761 EXPECT_EQ(expected_version, selected_version)
4762 << alt_svc_info.ToString() << " "
4763 << quic::ParsedQuicVersionVectorToString(advertised_versions);
4764 }
4765
TEST_P(HttpStreamFactoryJobControllerTest,AltSvcVersionSelectionFindsFirstMatch)4766 TEST_P(HttpStreamFactoryJobControllerTest,
4767 AltSvcVersionSelectionFindsFirstMatch) {
4768 TestAltSvcVersionSelection(
4769 "h3-Q050=\":443\"; ma=2592000,"
4770 "h3-Q049=\":443\"; ma=2592000,"
4771 "h3-Q048=\":443\"; ma=2592000,"
4772 "h3-Q046=\":443\"; ma=2592000,",
4773 quic::ParsedQuicVersion::Q046(), quic::AllSupportedVersions());
4774 }
4775
TEST_P(HttpStreamFactoryJobControllerTest,AltSvcVersionSelectionFindsFirstMatchInverse)4776 TEST_P(HttpStreamFactoryJobControllerTest,
4777 AltSvcVersionSelectionFindsFirstMatchInverse) {
4778 TestAltSvcVersionSelection(
4779 "h3-Q046=\":443\"; ma=2592000,"
4780 "h3-Q048=\":443\"; ma=2592000,"
4781 "h3-Q049=\":443\"; ma=2592000,",
4782 quic::ParsedQuicVersion::Q046(), quic::AllSupportedVersions());
4783 }
4784
TEST_P(HttpStreamFactoryJobControllerTest,AltSvcVersionSelectionWithInverseOrderingNewFormat)4785 TEST_P(HttpStreamFactoryJobControllerTest,
4786 AltSvcVersionSelectionWithInverseOrderingNewFormat) {
4787 // Server prefers Q046 but client prefers Q050.
4788 TestAltSvcVersionSelection(
4789 "h3-Q046=\":443\"; ma=2592000,"
4790 "h3-Q050=\":443\"; ma=2592000",
4791 quic::ParsedQuicVersion::Q046(),
4792 quic::ParsedQuicVersionVector{quic::ParsedQuicVersion::Q046()});
4793 }
4794
4795 // Tests that if HttpNetworkSession has a non-empty QUIC host allowlist,
4796 // then GetAlternativeServiceFor() will not return any QUIC alternative service
4797 // that's not on the allowlist.
TEST_P(HttpStreamFactoryJobControllerTest,QuicHostAllowlist)4798 TEST_P(HttpStreamFactoryJobControllerTest, QuicHostAllowlist) {
4799 HttpRequestInfo request_info;
4800 request_info.method = "GET";
4801 request_info.url = GURL("https://www.google.com");
4802
4803 Initialize(request_info);
4804
4805 // Set HttpNetworkSession's QUIC host allowlist to only have www.example.com
4806 HttpNetworkSessionPeer session_peer(session_.get());
4807 session_peer.params()->quic_host_allowlist.insert("www.example.com");
4808 quic_context_.params()->allow_remote_alt_svc = true;
4809
4810 // Set alternative service for www.google.com to be www.example.com over QUIC.
4811 url::SchemeHostPort server(request_info.url);
4812 base::Time expiration = base::Time::Now() + base::Days(1);
4813 quic::ParsedQuicVersionVector supported_versions =
4814 quic_context_.params()->supported_versions;
4815 session_->http_server_properties()->SetQuicAlternativeService(
4816 server, NetworkAnonymizationKey(),
4817 AlternativeService(kProtoQUIC, "www.example.com", 443), expiration,
4818 supported_versions);
4819
4820 // Simulate proxy resolution succeeding, after which
4821 // GetAlternativeServiceInfoFor can be called.
4822 JobControllerPeer::InitializeProxyInfo(job_controller_);
4823
4824 AlternativeServiceInfo alt_svc_info =
4825 JobControllerPeer::GetAlternativeServiceInfoFor(
4826 job_controller_, request_info, &request_delegate_,
4827 HttpStreamRequest::HTTP_STREAM);
4828
4829 std::sort(
4830 supported_versions.begin(), supported_versions.end(),
4831 [](const quic::ParsedQuicVersion& a, const quic::ParsedQuicVersion& b) {
4832 return a.transport_version < b.transport_version;
4833 });
4834 quic::ParsedQuicVersionVector advertised_versions =
4835 alt_svc_info.advertised_versions();
4836 std::sort(
4837 advertised_versions.begin(), advertised_versions.end(),
4838 [](const quic::ParsedQuicVersion& a, const quic::ParsedQuicVersion& b) {
4839 return a.transport_version < b.transport_version;
4840 });
4841 EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol);
4842 EXPECT_EQ(supported_versions, advertised_versions);
4843
4844 session_->http_server_properties()->SetQuicAlternativeService(
4845 server, NetworkAnonymizationKey(),
4846 AlternativeService(kProtoQUIC, "www.example.org", 443), expiration,
4847 supported_versions);
4848
4849 alt_svc_info = JobControllerPeer::GetAlternativeServiceInfoFor(
4850 job_controller_, request_info, &request_delegate_,
4851 HttpStreamRequest::HTTP_STREAM);
4852
4853 EXPECT_EQ(kProtoUnknown, alt_svc_info.alternative_service().protocol);
4854 EXPECT_EQ(0u, alt_svc_info.advertised_versions().size());
4855 }
4856
4857 // Tests specific to UseDnsHttpsAlpn feature.
4858 class HttpStreamFactoryJobControllerDnsHttpsAlpnTest
4859 : public HttpStreamFactoryJobControllerTestBase {
4860 protected:
HttpStreamFactoryJobControllerDnsHttpsAlpnTest(std::vector<base::test::FeatureRef> enabled_features={})4861 explicit HttpStreamFactoryJobControllerDnsHttpsAlpnTest(
4862 std::vector<base::test::FeatureRef> enabled_features = {})
4863 : HttpStreamFactoryJobControllerTestBase(true,
4864 std::move(enabled_features)) {}
4865
SetUp()4866 void SetUp() override { SkipCreatingJobController(); }
4867
EnableOndemandHostResolver()4868 void EnableOndemandHostResolver() {
4869 session_deps_.host_resolver->set_synchronous_mode(false);
4870 session_deps_.host_resolver->set_ondemand_mode(true);
4871 }
4872
CreateTestHttpRequestInfo()4873 HttpRequestInfo CreateTestHttpRequestInfo() {
4874 HttpRequestInfo request_info;
4875 request_info.method = "GET";
4876 request_info.url = GURL("https://www.example.org");
4877 return request_info;
4878 }
4879
RegisterMockHttpsRecord()4880 void RegisterMockHttpsRecord() {
4881 HostResolverEndpointResult endpoint_result1;
4882 endpoint_result1.ip_endpoints = {IPEndPoint(IPAddress::IPv4Localhost(), 0)};
4883 endpoint_result1.metadata.supported_protocol_alpns = {
4884 quic::AlpnForVersion(version_)};
4885
4886 HostResolverEndpointResult endpoint_result2;
4887 endpoint_result2.ip_endpoints = {IPEndPoint(IPAddress::IPv4Localhost(), 0)};
4888
4889 std::vector<HostResolverEndpointResult> endpoints;
4890 endpoints.push_back(endpoint_result1);
4891 endpoints.push_back(endpoint_result2);
4892 session_deps_.host_resolver->rules()->AddRule(
4893 "www.example.org",
4894 MockHostResolverBase::RuleResolver::RuleResult(
4895 std::move(endpoints),
4896 /*aliases=*/std::set<std::string>{"www.example.org"}));
4897 }
4898
CreateJobController(const HttpRequestInfo & request_info)4899 void CreateJobController(const HttpRequestInfo& request_info) {
4900 CreateJobControllerImpl(&job_controller_, &request_delegate_, request_info);
4901 }
4902
CreateJobControllerAndStart(const HttpRequestInfo & request_info)4903 std::unique_ptr<HttpStreamRequest> CreateJobControllerAndStart(
4904 const HttpRequestInfo& request_info) {
4905 return CreateJobControllerAndStartImpl(&job_controller_, &request_delegate_,
4906 request_info);
4907 }
4908
CreateSecondJobControllerAndStart(const HttpRequestInfo & request_info)4909 std::unique_ptr<HttpStreamRequest> CreateSecondJobControllerAndStart(
4910 const HttpRequestInfo& request_info) {
4911 return CreateJobControllerAndStartImpl(&job_controller2_,
4912 &request_delegate2_, request_info);
4913 }
4914
PrepareForMainJob()4915 void PrepareForMainJob() { PrepareForMainJobImpl(&tcp_data_, &ssl_data_); }
PrepareForSecondMainJob()4916 void PrepareForSecondMainJob() {
4917 PrepareForMainJobImpl(&tcp_data2_, &ssl_data2_);
4918 }
4919
PrepareForFirstQuicJob()4920 void PrepareForFirstQuicJob() { PrepareForQuicJobImpl(&quic_data_); }
PrepareForSecondQuicJob()4921 void PrepareForSecondQuicJob() { PrepareForQuicJobImpl(&quic_data2_); }
4922
PrepareForFirstQuicJobFailure()4923 void PrepareForFirstQuicJobFailure() {
4924 PrepareForQuicJobFailureImpl(&quic_data_);
4925 }
PrepareForSecondQuicJobFailure()4926 void PrepareForSecondQuicJobFailure() {
4927 PrepareForQuicJobFailureImpl(&quic_data2_);
4928 }
4929
MakeMainJobSucceed(bool expect_stream_ready)4930 void MakeMainJobSucceed(bool expect_stream_ready) {
4931 MakeMainJobSucceedImpl(request_delegate_, tcp_data_.get(),
4932 expect_stream_ready);
4933 }
4934
MakeSecondMainJobSucceed(bool expect_stream_ready)4935 void MakeSecondMainJobSucceed(bool expect_stream_ready) {
4936 MakeMainJobSucceedImpl(request_delegate2_, tcp_data2_.get(),
4937 expect_stream_ready);
4938 }
4939
MakeQuicJobSucceed(size_t index,bool expect_stream_ready)4940 void MakeQuicJobSucceed(size_t index, bool expect_stream_ready) {
4941 base::RunLoop().RunUntilIdle();
4942 ASSERT_GT(crypto_client_stream_factory_.streams().size(), index);
4943 MockCryptoClientStream* stream =
4944 crypto_client_stream_factory_.streams()[index].get();
4945 ASSERT_TRUE(stream);
4946
4947 if (expect_stream_ready) {
4948 base::RunLoop run_loop;
4949 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
4950 .Times(1)
4951 .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); }));
4952 stream->NotifySessionOneRttKeyAvailable();
4953 run_loop.Run();
4954 } else {
4955 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _)).Times(0);
4956 stream->NotifySessionOneRttKeyAvailable();
4957 base::RunLoop().RunUntilIdle();
4958 }
4959 }
4960
CheckJobsStatus(bool main_job_exists,bool alternative_job_exists,bool dns_alpn_h3_job_exists,const std::string & scoped_trace_message="")4961 void CheckJobsStatus(bool main_job_exists,
4962 bool alternative_job_exists,
4963 bool dns_alpn_h3_job_exists,
4964 const std::string& scoped_trace_message = "") {
4965 CheckJobsStatusImpl(job_controller_.get(), main_job_exists,
4966 alternative_job_exists, dns_alpn_h3_job_exists,
4967 scoped_trace_message);
4968 }
4969
CheckSecondJobsStatus(bool main_job_exists,bool alternative_job_exists,bool dns_alpn_h3_job_exists,const std::string & scoped_trace_message="")4970 void CheckSecondJobsStatus(bool main_job_exists,
4971 bool alternative_job_exists,
4972 bool dns_alpn_h3_job_exists,
4973 const std::string& scoped_trace_message = "") {
4974 CheckJobsStatusImpl(job_controller2_.get(), main_job_exists,
4975 alternative_job_exists, dns_alpn_h3_job_exists,
4976 scoped_trace_message);
4977 }
4978
ConnectQuicHttpStream(bool alt_destination,bool require_dns_https_alpn)4979 std::unique_ptr<QuicHttpStream> ConnectQuicHttpStream(
4980 bool alt_destination,
4981 bool require_dns_https_alpn) {
4982 NetErrorDetails net_error_details;
4983 QuicSessionRequest quic_request(session_->quic_session_pool());
4984 url::SchemeHostPort scheme_host_port(
4985 url::kHttpsScheme,
4986 alt_destination ? "alt.example.org" : "www.example.org", 443);
4987 std::optional<int> quic_request_result;
4988
4989 CHECK_EQ(ERR_IO_PENDING,
4990 quic_request.Request(
4991 scheme_host_port,
4992 require_dns_https_alpn ? quic::ParsedQuicVersion::Unsupported()
4993 : version_,
4994 ProxyChain::Direct(), TRAFFIC_ANNOTATION_FOR_TESTS,
4995 /*http_user_agent_settings=*/nullptr,
4996 SessionUsage::kDestination, PRIVACY_MODE_DISABLED,
4997 DEFAULT_PRIORITY, SocketTag(), NetworkAnonymizationKey(),
4998 SecureDnsPolicy::kAllow, require_dns_https_alpn,
4999 /*cert_verify_flags=*/0, GURL("https://www.example.org/"),
5000 net_log_with_source_, &net_error_details,
5001 base::BindLambdaForTesting([&](int result) {}),
5002 base::BindLambdaForTesting([&quic_request_result](int result) {
5003 quic_request_result = result;
5004 })));
5005 base::RunLoop().RunUntilIdle();
5006 CHECK_EQ(1u, crypto_client_stream_factory_.streams().size());
5007 CHECK(crypto_client_stream_factory_.streams()[0]);
5008 crypto_client_stream_factory_.streams()[0]
5009 ->NotifySessionOneRttKeyAvailable();
5010 base::RunLoop().RunUntilIdle();
5011 CHECK(quic_request_result);
5012 CHECK_EQ(OK, *quic_request_result);
5013
5014 std::unique_ptr<QuicChromiumClientSession::Handle> session =
5015 quic_request.ReleaseSessionHandle();
5016 std::set<std::string> dns_aliases =
5017 session->GetDnsAliasesForSessionKey(quic_request.session_key());
5018 auto stream = std::make_unique<QuicHttpStream>(std::move(session),
5019 std::move(dns_aliases));
5020 return stream;
5021 }
5022
IsAlternativeServiceBroken(GURL & url)5023 bool IsAlternativeServiceBroken(GURL& url) {
5024 return session_->http_server_properties()->IsAlternativeServiceBroken(
5025 AlternativeService(kProtoQUIC, HostPortPair::FromURL(url)),
5026 NetworkAnonymizationKey());
5027 }
5028
5029 raw_ptr<HttpStreamFactory::JobController, AcrossTasksDanglingUntriaged>
5030 job_controller2_ = nullptr;
5031
5032 MockHttpStreamRequestDelegate request_delegate2_;
5033
5034 private:
CreateQuicTestPacketMakerForClient()5035 QuicTestPacketMaker CreateQuicTestPacketMakerForClient() {
5036 return QuicTestPacketMaker(version_,
5037 quic::QuicUtils::CreateRandomConnectionId(
5038 quic_context_.random_generator()),
5039 quic_context_.clock(), "www.example.org",
5040 quic::Perspective::IS_CLIENT, false);
5041 }
5042
CreateJobControllerImpl(raw_ptr<HttpStreamFactory::JobController,AcrossTasksDanglingUntriaged> * job_controller,MockHttpStreamRequestDelegate * request_delegate,const HttpRequestInfo & request_info)5043 void CreateJobControllerImpl(
5044 raw_ptr<HttpStreamFactory::JobController, AcrossTasksDanglingUntriaged>*
5045 job_controller,
5046 MockHttpStreamRequestDelegate* request_delegate,
5047 const HttpRequestInfo& request_info) {
5048 auto controller = std::make_unique<HttpStreamFactory::JobController>(
5049 factory_, request_delegate, session_.get(), &default_job_factory_,
5050 request_info, is_preconnect_, /*is_websocket=*/false,
5051 enable_ip_based_pooling_, enable_alternative_services_,
5052 delay_main_job_with_available_spdy_session_,
5053 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
5054 *job_controller = controller.get();
5055 HttpStreamFactoryPeer::AddJobController(factory_, std::move(controller));
5056 }
5057
CreateJobControllerAndStartImpl(raw_ptr<HttpStreamFactory::JobController,AcrossTasksDanglingUntriaged> * job_controller,MockHttpStreamRequestDelegate * request_delegate,const HttpRequestInfo & request_info)5058 std::unique_ptr<HttpStreamRequest> CreateJobControllerAndStartImpl(
5059 raw_ptr<HttpStreamFactory::JobController, AcrossTasksDanglingUntriaged>*
5060 job_controller,
5061 MockHttpStreamRequestDelegate* request_delegate,
5062 const HttpRequestInfo& request_info) {
5063 CreateJobControllerImpl(job_controller, request_delegate, request_info);
5064 return (*job_controller)
5065 ->Start(request_delegate, nullptr, net_log_with_source_,
5066 HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
5067 }
5068
PrepareForMainJobImpl(std::unique_ptr<SequencedSocketData> * tcp_data,std::unique_ptr<SSLSocketDataProvider> * ssl_data)5069 void PrepareForMainJobImpl(std::unique_ptr<SequencedSocketData>* tcp_data,
5070 std::unique_ptr<SSLSocketDataProvider>* ssl_data) {
5071 *tcp_data = std::make_unique<SequencedSocketData>();
5072 (*tcp_data)->set_connect_data(
5073 MockConnect(ASYNC, ERR_IO_PENDING)); /* pause */
5074 (*ssl_data) = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
5075 session_deps_.socket_factory->AddSSLSocketDataProvider(ssl_data->get());
5076 }
5077
PrepareForQuicJobImpl(std::unique_ptr<MockQuicData> * quic_data)5078 void PrepareForQuicJobImpl(std::unique_ptr<MockQuicData>* quic_data) {
5079 crypto_client_stream_factory_.set_handshake_mode(
5080 MockCryptoClientStream::COLD_START);
5081 *quic_data = std::make_unique<MockQuicData>(version_);
5082 (*quic_data)->AddRead(SYNCHRONOUS, ERR_IO_PENDING);
5083 (*quic_data)
5084 ->AddWrite(
5085 SYNCHRONOUS,
5086 CreateQuicTestPacketMakerForClient().MakeInitialSettingsPacket(1));
5087 }
5088
PrepareForQuicJobFailureImpl(std::unique_ptr<MockQuicData> * quic_data)5089 void PrepareForQuicJobFailureImpl(std::unique_ptr<MockQuicData>* quic_data) {
5090 crypto_client_stream_factory_.set_handshake_mode(
5091 MockCryptoClientStream::COLD_START);
5092 *quic_data = std::make_unique<MockQuicData>(version_);
5093 (*quic_data)->AddRead(ASYNC, ERR_IO_PENDING); // Pause
5094 (*quic_data)->AddRead(ASYNC, ERR_FAILED);
5095 }
5096
MakeMainJobSucceedImpl(MockHttpStreamRequestDelegate & request_delegate,SequencedSocketData * tcp_data,bool expect_stream_ready)5097 void MakeMainJobSucceedImpl(MockHttpStreamRequestDelegate& request_delegate,
5098 SequencedSocketData* tcp_data,
5099 bool expect_stream_ready) {
5100 if (expect_stream_ready) {
5101 base::RunLoop run_loop;
5102 EXPECT_CALL(request_delegate, OnStreamReadyImpl(_, _))
5103 .Times(1)
5104 .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); }));
5105 tcp_data->socket()->OnConnectComplete(MockConnect());
5106 run_loop.Run();
5107 } else {
5108 EXPECT_CALL(request_delegate, OnStreamReadyImpl(_, _)).Times(0);
5109 tcp_data->socket()->OnConnectComplete(MockConnect());
5110 base::RunLoop().RunUntilIdle();
5111 }
5112 }
5113
CheckJobsStatusImpl(HttpStreamFactory::JobController * job_controller,bool main_job_exists,bool alternative_job_exists,bool dns_alpn_h3_job_exists,const std::string & scoped_trace_message)5114 static void CheckJobsStatusImpl(
5115 HttpStreamFactory::JobController* job_controller,
5116 bool main_job_exists,
5117 bool alternative_job_exists,
5118 bool dns_alpn_h3_job_exists,
5119 const std::string& scoped_trace_message) {
5120 SCOPED_TRACE(scoped_trace_message);
5121 EXPECT_EQ(main_job_exists, !!job_controller->main_job());
5122 EXPECT_EQ(alternative_job_exists, !!job_controller->alternative_job());
5123 EXPECT_EQ(dns_alpn_h3_job_exists, !!job_controller->dns_alpn_h3_job());
5124 }
5125
5126 // Use real Jobs so that Job::Resume() is not mocked out. When main job is
5127 // resumed it will use mock socket data.
5128 HttpStreamFactory::JobFactory default_job_factory_;
5129
5130 // Used for man job connection.
5131 std::unique_ptr<SSLSocketDataProvider> ssl_data_;
5132 std::unique_ptr<SSLSocketDataProvider> ssl_data2_;
5133 };
5134
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,NoHttpsRecordSyncHostResolve)5135 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5136 NoHttpsRecordSyncHostResolve) {
5137 PrepareForMainJob();
5138 Initialize(HttpRequestInfo());
5139 request_ = CreateJobControllerAndStart(CreateTestHttpRequestInfo());
5140
5141 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5142 /*dns_alpn_h3_job_exists=*/true,
5143 "Main job and DNS ALPN job must be created.");
5144
5145 // The main job should be synchronously resumed, as host is resolved
5146 // synchronously.
5147 EXPECT_FALSE(job_controller_->main_job()->is_waiting());
5148
5149 base::RunLoop().RunUntilIdle();
5150
5151 // |dns_alpn_h3_job| must fail when there is no valid supported alpn. And
5152 // must be deleted.
5153 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5154 /*dns_alpn_h3_job_exists=*/false,
5155 "DNS ALPN job must be deleted.");
5156
5157 base::HistogramTester histogram_tester;
5158 MakeMainJobSucceed(/*expect_stream_ready=*/true);
5159 // Net.AlternateProtocolUsage records
5160 // ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON, when only main job exists.
5161 histogram_tester.ExpectUniqueSample(
5162 "Net.AlternateProtocolUsage", ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON,
5163 1);
5164
5165 request_.reset();
5166 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5167 }
5168
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,NoHttpsRecordAsyncHostResolveResumeMainWithoutDelay)5169 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5170 NoHttpsRecordAsyncHostResolveResumeMainWithoutDelay) {
5171 EnableOndemandHostResolver();
5172 PrepareForMainJob();
5173 Initialize(HttpRequestInfo());
5174
5175 request_ = CreateJobControllerAndStart(CreateTestHttpRequestInfo());
5176
5177 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5178 /*dns_alpn_h3_job_exists=*/true,
5179 "Main job and DNS ALPN job must be created.");
5180
5181 // The main job should be resumed quickly after resolving the host.
5182 EXPECT_TRUE(job_controller_->main_job()->is_waiting());
5183
5184 // Resolve the host resolve request from |dns_alpn_h3_job|.
5185 session_deps_.host_resolver->ResolveAllPending();
5186 base::RunLoop().RunUntilIdle();
5187
5188 // |dns_alpn_h3_job| must fail when there is no valid supported alpn. And
5189 // must be deleted.
5190 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5191 /*dns_alpn_h3_job_exists=*/false,
5192 "DNS ALPN job must be deleted.");
5193 EXPECT_FALSE(job_controller_->main_job()->is_waiting());
5194
5195 // The host resolve request from the main job must be resolved using the
5196 // cached result.
5197 EXPECT_TRUE(tcp_data_->socket());
5198
5199 base::HistogramTester histogram_tester;
5200 MakeMainJobSucceed(/*expect_stream_ready=*/true);
5201 // Net.AlternateProtocolUsage records
5202 // ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON, when only main job exists.
5203 histogram_tester.ExpectUniqueSample(
5204 "Net.AlternateProtocolUsage", ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON,
5205 1);
5206
5207 request_.reset();
5208 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5209 }
5210
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,NoHttpsRecordAsyncHostResolveResumeMainWithoutDelayQuicWorkedNetwork)5211 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5212 NoHttpsRecordAsyncHostResolveResumeMainWithoutDelayQuicWorkedNetwork) {
5213 EnableOndemandHostResolver();
5214 PrepareForMainJob();
5215 Initialize(HttpRequestInfo());
5216
5217 QuicSessionPool* quic_session_pool = session_->quic_session_pool();
5218 quic_session_pool->set_is_quic_known_to_work_on_current_network(true);
5219
5220 request_ = CreateJobControllerAndStart(CreateTestHttpRequestInfo());
5221
5222 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5223 /*dns_alpn_h3_job_exists=*/true,
5224 "Main job and DNS ALPN job must be created.");
5225 // Main job must be waiting.
5226 EXPECT_TRUE(job_controller_->main_job()->is_waiting());
5227
5228 // Resolve the host resolve request from |dns_alpn_h3_job|.
5229 session_deps_.host_resolver->ResolveAllPending();
5230 base::RunLoop().RunUntilIdle();
5231
5232 // |dns_alpn_h3_job| must fail when there is no valid supported alpn. And
5233 // must be deleted.
5234 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5235 /*dns_alpn_h3_job_exists=*/false,
5236 "DNS ALPN job must be deleted.");
5237 // The main job should be resumed quickly after resolving the host.
5238 EXPECT_FALSE(job_controller_->main_job()->is_waiting());
5239
5240 // The host resolve request from the main job must be resolved using the
5241 // cached result.
5242 EXPECT_TRUE(tcp_data_->socket());
5243
5244 base::HistogramTester histogram_tester;
5245 MakeMainJobSucceed(/*expect_stream_ready=*/true);
5246 // Net.AlternateProtocolUsage records
5247 // ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON, when only main job exists.
5248 histogram_tester.ExpectUniqueSample(
5249 "Net.AlternateProtocolUsage", ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON,
5250 1);
5251
5252 request_.reset();
5253 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5254 }
5255
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,MainJobNoDelayOnQuicNotWorkedNetworkSyncHostResolve)5256 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5257 MainJobNoDelayOnQuicNotWorkedNetworkSyncHostResolve) {
5258 PrepareForMainJob();
5259 PrepareForFirstQuicJob();
5260 RegisterMockHttpsRecord();
5261
5262 Initialize(HttpRequestInfo());
5263
5264 request_ = CreateJobControllerAndStart(CreateTestHttpRequestInfo());
5265
5266 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5267 /*dns_alpn_h3_job_exists=*/true,
5268 "Main job and DNS ALPN job must be created.");
5269 // `dns_alpn_h3_job` should not be waiting for dns host
5270 // resolution as that was resolved synchronously.
5271 EXPECT_FALSE(job_controller_->dns_alpn_h3_job()
5272 ->expect_on_quic_host_resolution_for_tests());
5273
5274 base::HistogramTester histogram_tester;
5275 // Make |dns_alpn_h3_job| succeed.
5276 MakeQuicJobSucceed(0, /*expect_stream_ready=*/true);
5277 histogram_tester.ExpectUniqueSample(
5278 "Net.AlternateProtocolUsage",
5279 ALTERNATE_PROTOCOL_USAGE_DNS_ALPN_H3_JOB_WON_RACE, 1);
5280
5281 // The success of |dns_alpn_h3_job| deletes |main_job|.
5282 CheckJobsStatus(/*main_job_exists=*/false, /*alternative_job_exists=*/false,
5283 /*dns_alpn_h3_job_exists=*/true, "Main job must be deleted.");
5284
5285 request_.reset();
5286 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5287 }
5288
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,MainJobNoDelayOnQuicNotWorkedNetworkAsyncHostResolve)5289 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5290 MainJobNoDelayOnQuicNotWorkedNetworkAsyncHostResolve) {
5291 EnableOndemandHostResolver();
5292 PrepareForMainJob();
5293 PrepareForFirstQuicJob();
5294 RegisterMockHttpsRecord();
5295
5296 Initialize(HttpRequestInfo());
5297
5298 request_ = CreateJobControllerAndStart(CreateTestHttpRequestInfo());
5299
5300 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5301 /*dns_alpn_h3_job_exists=*/true,
5302 "Main job and DNS ALPN job must be created.");
5303
5304 // |main_job| is blocked until host resolves.
5305 EXPECT_TRUE(job_controller_->main_job()->is_waiting());
5306 base::RunLoop().RunUntilIdle();
5307 EXPECT_TRUE(job_controller_->main_job()->is_waiting());
5308
5309 // Resolve the host resolve request from |dns_alpn_h3_job|.
5310 session_deps_.host_resolver->ResolveAllPending();
5311 EXPECT_TRUE(job_controller_->main_job()->is_waiting());
5312 base::RunLoop().RunUntilIdle();
5313
5314 // |main_job| should have been resumed quickly because
5315 // |is_quic_known_to_work_on_current_network| is false for this test.
5316 EXPECT_FALSE(job_controller_->main_job()->is_waiting());
5317 // |dns_alpn_h3_job| must not fail when there is a valid supported alpn.
5318 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5319 /*dns_alpn_h3_job_exists=*/true,
5320 "Both main job and DNS ALPN job must be alive");
5321
5322 base::HistogramTester histogram_tester;
5323 // Make |dns_alpn_h3_job| succeed.
5324 MakeQuicJobSucceed(0, /*expect_stream_ready=*/true);
5325 histogram_tester.ExpectUniqueSample(
5326 "Net.AlternateProtocolUsage",
5327 ALTERNATE_PROTOCOL_USAGE_DNS_ALPN_H3_JOB_WON_RACE, 1);
5328
5329 // The success of |dns_alpn_h3_job| deletes |main_job|.
5330 CheckJobsStatus(/*main_job_exists=*/false, /*alternative_job_exists=*/false,
5331 /*dns_alpn_h3_job_exists=*/true, "Main job must be deleted.");
5332
5333 request_.reset();
5334 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5335 }
5336
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,MainJobDelayOnQuicWorkedNetwork)5337 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5338 MainJobDelayOnQuicWorkedNetwork) {
5339 PrepareForMainJob();
5340 PrepareForFirstQuicJob();
5341 RegisterMockHttpsRecord();
5342
5343 Initialize(HttpRequestInfo());
5344 QuicSessionPool* quic_session_pool = session_->quic_session_pool();
5345 quic_session_pool->set_is_quic_known_to_work_on_current_network(true);
5346
5347 request_ = CreateJobControllerAndStart(CreateTestHttpRequestInfo());
5348
5349 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5350 /*dns_alpn_h3_job_exists=*/true,
5351 "Main job and DNS ALPN job must be created.");
5352 base::RunLoop().RunUntilIdle();
5353 // |dns_alpn_h3_job| must not fail when there is a valid supported alpn.
5354 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5355 /*dns_alpn_h3_job_exists=*/true,
5356 "Both main job and DNS ALPN job must be alive");
5357
5358 // The main job should be waiting until kDefaultDelayMilliSecsForWaitingJob
5359 // amount of time has passed.
5360 EXPECT_TRUE(job_controller_->main_job()->is_waiting());
5361 FastForwardBy(base::Milliseconds(kDefaultDelayMilliSecsForWaitingJob - 1));
5362 EXPECT_TRUE(job_controller_->main_job()->is_waiting());
5363 FastForwardBy(base::Milliseconds(1));
5364 EXPECT_FALSE(job_controller_->main_job()->is_waiting());
5365
5366 base::HistogramTester histogram_tester;
5367 // Make |dns_alpn_h3_job| succeed.
5368 MakeQuicJobSucceed(0, /*expect_stream_ready=*/true);
5369 histogram_tester.ExpectUniqueSample(
5370 "Net.AlternateProtocolUsage",
5371 ALTERNATE_PROTOCOL_USAGE_DNS_ALPN_H3_JOB_WON_RACE, 1);
5372
5373 // The success of |dns_alpn_h3_job| deletes |main_job|.
5374 CheckJobsStatus(/*main_job_exists=*/false, /*alternative_job_exists=*/false,
5375 /*dns_alpn_h3_job_exists=*/true, "Main job must be deleted.");
5376
5377 request_.reset();
5378 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5379 }
5380
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,MainJobSucceedsDnsAlpnH3JobSucceeds)5381 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5382 MainJobSucceedsDnsAlpnH3JobSucceeds) {
5383 PrepareForMainJob();
5384 PrepareForFirstQuicJob();
5385 RegisterMockHttpsRecord();
5386
5387 Initialize(HttpRequestInfo());
5388 request_ = CreateJobControllerAndStart(CreateTestHttpRequestInfo());
5389 base::RunLoop().RunUntilIdle();
5390
5391 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5392 /*dns_alpn_h3_job_exists=*/true,
5393 "Main job and DNS ALPN job must be created.");
5394 // |main_job| is not blocked, because the hostname is resolved synchronously
5395 // and |is_quic_known_to_work_on_current_network| is false for this test.
5396 EXPECT_FALSE(job_controller_->main_job()->is_waiting());
5397
5398 base::HistogramTester histogram_tester;
5399 // Make |main_job| succeed.
5400 MakeMainJobSucceed(/*expect_stream_ready=*/true);
5401 histogram_tester.ExpectUniqueSample(
5402 "Net.AlternateProtocolUsage", ALTERNATE_PROTOCOL_USAGE_MAIN_JOB_WON_RACE,
5403 1);
5404
5405 // The success of |main_job| doesn't delete |dns_alpn_h3_job|.
5406 EXPECT_TRUE(job_controller_->dns_alpn_h3_job());
5407
5408 // Make |dns_alpn_h3_job| complete.
5409 MakeQuicJobSucceed(0, /*expect_stream_ready=*/false);
5410
5411 request_.reset();
5412 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5413 }
5414
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,ActiveSessionAvailableForMainJob)5415 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5416 ActiveSessionAvailableForMainJob) {
5417 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
5418 PrepareForFirstQuicJob();
5419
5420 RegisterMockHttpsRecord();
5421
5422 Initialize(HttpRequestInfo());
5423
5424 // Set |is_quic_known_to_work_on_current_network| flag so that
5425 // the delaying logic of main job would work when the main job is blocked.
5426 // Note: In this test, we don't need this because the main job is not blocked.
5427 // But we set here because we want to check that the main job is not blocked.
5428 QuicSessionPool* quic_session_pool = session_->quic_session_pool();
5429 quic_session_pool->set_is_quic_known_to_work_on_current_network(true);
5430
5431 // Put a SpdySession in the pool.
5432 SpdySessionKey key(HostPortPair::FromURL(request_info.url),
5433 PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
5434 SessionUsage::kDestination, SocketTag(),
5435 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
5436 /*disable_cert_verification_network_fetches=*/false);
5437 std::ignore = CreateFakeSpdySession(session_->spdy_session_pool(), key);
5438
5439 request_ = CreateJobControllerAndStart(request_info);
5440 // |dns_alpn_h3_job| must be created even when an active session is
5441 // available for |main_job|.
5442 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5443 /*dns_alpn_h3_job_exists=*/true,
5444 "Main job and DNS ALPN job must be created.");
5445
5446 // Main job must not be waiting because an active session is available.
5447 EXPECT_FALSE(job_controller_->main_job()->is_waiting());
5448
5449 base::HistogramTester histogram_tester;
5450 // Run the message loop to make |main_job| succeed and status will be
5451 // reported to Request.
5452 {
5453 base::RunLoop run_loop;
5454 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
5455 .Times(1)
5456 .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); }));
5457 run_loop.Run();
5458 }
5459 histogram_tester.ExpectUniqueSample(
5460 "Net.AlternateProtocolUsage", ALTERNATE_PROTOCOL_USAGE_MAIN_JOB_WON_RACE,
5461 1);
5462
5463 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5464 /*dns_alpn_h3_job_exists=*/true,
5465 "DNS ALPN job must be alive");
5466
5467 // Make |dns_alpn_h3_job| succeed.
5468 MakeQuicJobSucceed(0, /*expect_stream_ready=*/false);
5469 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5470 /*dns_alpn_h3_job_exists=*/false,
5471 "DNS ALPN job must be deleted");
5472
5473 request_.reset();
5474 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5475 }
5476
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,MainJobHasActiveSocket)5477 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest, MainJobHasActiveSocket) {
5478 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
5479
5480 PrepareForMainJob();
5481 PrepareForSecondMainJob();
5482
5483 PrepareForFirstQuicJobFailure();
5484 RegisterMockHttpsRecord();
5485
5486 Initialize(HttpRequestInfo());
5487
5488 // Set |is_quic_known_to_work_on_current_network| flag so that
5489 // the delaying logic of main job would work when the main job is blocked.
5490 QuicSessionPool* quic_session_pool = session_->quic_session_pool();
5491 quic_session_pool->set_is_quic_known_to_work_on_current_network(true);
5492
5493 request_ = CreateJobControllerAndStart(request_info);
5494 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5495 /*dns_alpn_h3_job_exists=*/true,
5496 "Main job and DNS ALPN job must be created.");
5497
5498 EXPECT_TRUE(job_controller_->main_job()->is_waiting());
5499 FastForwardBy(base::Milliseconds(kDefaultDelayMilliSecsForWaitingJob - 1));
5500 EXPECT_TRUE(job_controller_->main_job()->is_waiting());
5501 FastForwardBy(base::Milliseconds(1));
5502 EXPECT_FALSE(job_controller_->main_job()->is_waiting());
5503
5504 auto request2 = CreateSecondJobControllerAndStart(request_info);
5505 CheckSecondJobsStatus(
5506 /*main_job_exists=*/true, /*alternative_job_exists=*/false,
5507 /*dns_alpn_h3_job_exists=*/true,
5508 "Main job and DNS ALPN job must be created for the second request.");
5509
5510 // When an active socket is available for the main job, the main job should
5511 // not be blocked.
5512 EXPECT_FALSE(job_controller2_->main_job()->is_waiting());
5513
5514 quic_data_->Resume();
5515 base::RunLoop().RunUntilIdle();
5516
5517 MakeMainJobSucceed(/*expect_stream_ready=*/true);
5518 MakeSecondMainJobSucceed(/*expect_stream_ready=*/true);
5519 }
5520
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,MainJobHasActiveSocketAltSvcRegistered)5521 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5522 MainJobHasActiveSocketAltSvcRegistered) {
5523 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
5524
5525 PrepareForMainJob();
5526 PrepareForSecondMainJob();
5527
5528 PrepareForFirstQuicJobFailure();
5529 PrepareForSecondQuicJobFailure();
5530
5531 RegisterMockHttpsRecord();
5532
5533 Initialize(HttpRequestInfo());
5534
5535 // Set |is_quic_known_to_work_on_current_network| flag so that
5536 // the delaying logic of main job would work when the main job is blocked.
5537 QuicSessionPool* quic_session_pool = session_->quic_session_pool();
5538 quic_session_pool->set_is_quic_known_to_work_on_current_network(true);
5539
5540 url::SchemeHostPort server(request_info.url);
5541 AlternativeService alternative_service(kProtoQUIC, "alt.example.org", 443);
5542 SetAlternativeService(request_info, alternative_service);
5543
5544 request_ = CreateJobControllerAndStart(request_info);
5545 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/true,
5546 /*dns_alpn_h3_job_exists=*/true,
5547 "All types of jobs are created");
5548
5549 EXPECT_TRUE(job_controller_->main_job()->is_waiting());
5550 FastForwardBy(base::Milliseconds(kDefaultDelayMilliSecsForWaitingJob - 1));
5551 EXPECT_TRUE(job_controller_->main_job()->is_waiting());
5552 FastForwardBy(base::Milliseconds(1));
5553 EXPECT_FALSE(job_controller_->main_job()->is_waiting());
5554
5555 auto request2 = CreateSecondJobControllerAndStart(request_info);
5556 CheckSecondJobsStatus(
5557 /*main_job_exists=*/true, /*alternative_job_exists=*/true,
5558 /*dns_alpn_h3_job_exists=*/true,
5559 "All types of jobs must be created for the second request.");
5560
5561 // The main job should be waiting until kDefaultDelayMilliSecsForWaitingJob
5562 // amount of time has passed, when an alternative service was registered,
5563 // even when an active socket is available for the main job.
5564 // This is intended to switch to QUIC from TCP for the first connection
5565 // when the server supports Alt-Svc but doesn't support HTTP DNS records with
5566 // alpn.
5567 // Note: When QuicParams.delay_main_job_with_available_spdy_session is false,
5568 // main job is not blocked.
5569 EXPECT_TRUE(job_controller2_->main_job()->is_waiting());
5570 FastForwardBy(base::Milliseconds(kDefaultDelayMilliSecsForWaitingJob - 1));
5571 EXPECT_TRUE(job_controller2_->main_job()->is_waiting());
5572 FastForwardBy(base::Milliseconds(1));
5573 EXPECT_FALSE(job_controller2_->main_job()->is_waiting());
5574
5575 quic_data_->Resume();
5576 quic_data2_->Resume();
5577 base::RunLoop().RunUntilIdle();
5578
5579 MakeMainJobSucceed(/*expect_stream_ready=*/true);
5580 MakeSecondMainJobSucceed(/*expect_stream_ready=*/true);
5581 }
5582
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,ActiveSessionAvailableForAltSvcJob)5583 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5584 ActiveSessionAvailableForAltSvcJob) {
5585 PrepareForMainJob();
5586 RegisterMockHttpsRecord();
5587
5588 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
5589
5590 PrepareForFirstQuicJob();
5591
5592 Initialize(HttpRequestInfo());
5593
5594 std::unique_ptr<QuicHttpStream> stream =
5595 ConnectQuicHttpStream(/*alt_destination=*/true,
5596 /*require_dns_https_alpn=*/false);
5597
5598 url::SchemeHostPort server(request_info.url);
5599 AlternativeService alternative_service(kProtoQUIC, "alt.example.org", 443);
5600 SetAlternativeService(request_info, alternative_service);
5601
5602 request_ = CreateJobControllerAndStart(request_info);
5603
5604 // |dns_alpn_h3_job| must not be created when an active session is
5605 // available for |alternative_job|.
5606 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/true,
5607 /*dns_alpn_h3_job_exists=*/false,
5608 "Main job and alternative job must be created.");
5609
5610 base::HistogramTester histogram_tester;
5611 // Run the message loop to make |alternative_job| succeed and status will be
5612 // reported to Request.
5613 {
5614 base::RunLoop run_loop;
5615 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
5616 .Times(1)
5617 .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); }));
5618 run_loop.Run();
5619 }
5620 histogram_tester.ExpectUniqueSample("Net.AlternateProtocolUsage",
5621 ALTERNATE_PROTOCOL_USAGE_NO_RACE, 1);
5622
5623 CheckJobsStatus(/*main_job_exists=*/false, /*alternative_job_exists=*/true,
5624 /*dns_alpn_h3_job_exists=*/false,
5625 "Main job must be deleted.");
5626
5627 request_.reset();
5628 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5629 }
5630
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,ActiveSessionAvailableForDnsAlpnH3Job)5631 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5632 ActiveSessionAvailableForDnsAlpnH3Job) {
5633 PrepareForFirstQuicJob();
5634 RegisterMockHttpsRecord();
5635
5636 Initialize(HttpRequestInfo());
5637
5638 std::unique_ptr<QuicHttpStream> stream =
5639 ConnectQuicHttpStream(/*alt_destination=*/false,
5640 /*require_dns_https_alpn=*/true);
5641 request_ = CreateJobControllerAndStart(CreateTestHttpRequestInfo());
5642
5643 CheckJobsStatus(/*main_job_exists=*/false, /*alternative_job_exists=*/false,
5644 /*dns_alpn_h3_job_exists=*/true,
5645 "Main job and alternative job must not be available.");
5646
5647 base::HistogramTester histogram_tester;
5648 // Run the message loop to make |dns_alpn_h3_job| succeed and status will be
5649 // reported to Request.
5650 {
5651 base::RunLoop run_loop;
5652 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
5653 .Times(1)
5654 .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); }));
5655 run_loop.Run();
5656 }
5657 histogram_tester.ExpectUniqueSample(
5658 "Net.AlternateProtocolUsage",
5659 ALTERNATE_PROTOCOL_USAGE_DNS_ALPN_H3_JOB_WON_WITHOUT_RACE, 1);
5660 CheckJobsStatus(/*main_job_exists=*/false, /*alternative_job_exists=*/false,
5661 /*dns_alpn_h3_job_exists=*/true,
5662 "DNS alpn H3 job must exist.");
5663
5664 request_.reset();
5665 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5666 }
5667
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,ActiveSessionAvailableForMainJobAndDnsAlpnH3Job)5668 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5669 ActiveSessionAvailableForMainJobAndDnsAlpnH3Job) {
5670 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
5671 PrepareForFirstQuicJob();
5672
5673 RegisterMockHttpsRecord();
5674
5675 Initialize(HttpRequestInfo());
5676
5677 // Put a SpdySession in the pool.
5678 SpdySessionKey key(HostPortPair::FromURL(request_info.url),
5679 PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
5680 SessionUsage::kDestination, SocketTag(),
5681 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
5682 /*disable_cert_verification_network_fetches=*/false);
5683 std::ignore = CreateFakeSpdySession(session_->spdy_session_pool(), key);
5684
5685 std::unique_ptr<QuicHttpStream> stream =
5686 ConnectQuicHttpStream(/*alt_destination=*/false,
5687 /*require_dns_https_alpn=*/true);
5688 request_ = CreateJobControllerAndStart(CreateTestHttpRequestInfo());
5689
5690 CheckJobsStatus(/*main_job_exists=*/false, /*alternative_job_exists=*/false,
5691 /*dns_alpn_h3_job_exists=*/true,
5692 "Main job must not be available.");
5693
5694 base::HistogramTester histogram_tester;
5695 // Run the message loop to make |dns_alpn_h3_job| succeed and status will be
5696 // reported to Request.
5697 {
5698 base::RunLoop run_loop;
5699 EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _))
5700 .Times(1)
5701 .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); }));
5702 run_loop.Run();
5703 }
5704 histogram_tester.ExpectUniqueSample(
5705 "Net.AlternateProtocolUsage",
5706 ALTERNATE_PROTOCOL_USAGE_DNS_ALPN_H3_JOB_WON_WITHOUT_RACE, 1);
5707
5708 CheckJobsStatus(/*main_job_exists=*/false, /*alternative_job_exists=*/false,
5709 /*dns_alpn_h3_job_exists=*/true,
5710 "DNS alpn H3 job must exist.");
5711
5712 request_.reset();
5713 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5714 }
5715
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,DoNotStartDnsAlpnH3JobWhenSameHostDefaultPortAltJobCreated)5716 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5717 DoNotStartDnsAlpnH3JobWhenSameHostDefaultPortAltJobCreated) {
5718 PrepareForMainJob();
5719 PrepareForFirstQuicJob();
5720
5721 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
5722
5723 RegisterMockHttpsRecord();
5724
5725 Initialize(HttpRequestInfo());
5726
5727 url::SchemeHostPort server(request_info.url);
5728 AlternativeService alternative_service(kProtoQUIC, "www.example.org", 443);
5729 SetAlternativeService(request_info, alternative_service);
5730
5731 request_ = CreateJobControllerAndStart(request_info);
5732 // |dns_alpn_h3_job| must be deleted when a same origin alt service
5733 // was registered.
5734 CheckJobsStatus(
5735 true, true, false,
5736 "All types of jobs are created, but DNS alpn job must be deleted");
5737
5738 base::RunLoop().RunUntilIdle();
5739 base::HistogramTester histogram_tester;
5740 // Make |main_job| succeed.
5741 MakeMainJobSucceed(/*expect_stream_ready=*/true);
5742 histogram_tester.ExpectUniqueSample(
5743 "Net.AlternateProtocolUsage", ALTERNATE_PROTOCOL_USAGE_MAIN_JOB_WON_RACE,
5744 1);
5745
5746 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/true,
5747 /*dns_alpn_h3_job_exists=*/false,
5748 "Alternate job must not be deleted");
5749
5750 // Make |alternative_job| succeed.
5751 MakeQuicJobSucceed(0, /*expect_stream_ready=*/false);
5752
5753 request_.reset();
5754 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5755 }
5756
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,AllJobsCreatedMainJobSucceedAltJobSucceedDnsJobSucceed)5757 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5758 AllJobsCreatedMainJobSucceedAltJobSucceedDnsJobSucceed) {
5759 PrepareForMainJob();
5760 PrepareForFirstQuicJob();
5761 PrepareForSecondQuicJob();
5762
5763 // Use cold start and complete `alternative_job` and `dns_alpn_h3_job`
5764 // manually.
5765 crypto_client_stream_factory_.set_handshake_mode(
5766 MockCryptoClientStream::COLD_START);
5767
5768 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
5769
5770 RegisterMockHttpsRecord();
5771
5772 Initialize(HttpRequestInfo());
5773
5774 url::SchemeHostPort server(request_info.url);
5775 AlternativeService alternative_service(kProtoQUIC, "alt.example.org", 443);
5776 SetAlternativeService(request_info, alternative_service);
5777
5778 request_ = CreateJobControllerAndStart(request_info);
5779 // |dns_alpn_h3_job| must be created when a different origin alt service
5780 // was registered.
5781 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/true,
5782 /*dns_alpn_h3_job_exists=*/true,
5783 "All types of jobs are created");
5784
5785 base::HistogramTester histogram_tester;
5786 base::RunLoop().RunUntilIdle();
5787 MakeMainJobSucceed(/*expect_stream_ready=*/true);
5788 histogram_tester.ExpectUniqueSample(
5789 "Net.AlternateProtocolUsage", ALTERNATE_PROTOCOL_USAGE_MAIN_JOB_WON_RACE,
5790 1);
5791
5792 // The success of |main_job| doesn't delete |alternative_job| and
5793 // |dns_alpn_h3_job|.
5794 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/true,
5795 /*dns_alpn_h3_job_exists=*/true, "Jobs must not be deleted.");
5796
5797 // Make |alternative_job| succeed.
5798 MakeQuicJobSucceed(0, /*expect_stream_ready=*/false);
5799 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5800 /*dns_alpn_h3_job_exists=*/true,
5801 "Alternate job must be deleted.");
5802
5803 // Make |dns_alpn_h3_job| succeed.
5804 MakeQuicJobSucceed(1, /*expect_stream_ready=*/false);
5805 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5806 /*dns_alpn_h3_job_exists=*/false,
5807 "DNS alpn job must be deleted.");
5808
5809 request_.reset();
5810 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5811 }
5812
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,AllJobsCreatedAltJobSucceedDnsJobSucceedMainJobSucceed)5813 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5814 AllJobsCreatedAltJobSucceedDnsJobSucceedMainJobSucceed) {
5815 PrepareForMainJob();
5816 PrepareForFirstQuicJob();
5817 PrepareForSecondQuicJob();
5818
5819 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
5820
5821 RegisterMockHttpsRecord();
5822
5823 Initialize(HttpRequestInfo());
5824
5825 url::SchemeHostPort server(request_info.url);
5826 AlternativeService alternative_service(kProtoQUIC, "alt.example.org", 443);
5827 SetAlternativeService(request_info, alternative_service);
5828
5829 request_ = CreateJobControllerAndStart(request_info);
5830 // |dns_alpn_h3_job| must be created when a different origin alt service
5831 // was registered.
5832 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/true,
5833 /*dns_alpn_h3_job_exists=*/true,
5834 "All types of jobs are created");
5835
5836 base::HistogramTester histogram_tester;
5837 // Make |alternative_job| succeed.
5838 MakeQuicJobSucceed(0, /*expect_stream_ready=*/true);
5839 histogram_tester.ExpectUniqueSample("Net.AlternateProtocolUsage",
5840 ALTERNATE_PROTOCOL_USAGE_WON_RACE, 1);
5841
5842 // The success of |alternative_job| doesn't delete |main_job| and
5843 // |dns_alpn_h3_job|.
5844 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/true,
5845 /*dns_alpn_h3_job_exists=*/true, "Jobs must not be deleted.");
5846
5847 // Make |dns_alpn_h3_job| succeed.
5848 MakeQuicJobSucceed(1, /*expect_stream_ready=*/false);
5849
5850 // The success of |dns_alpn_h3_job| doesn't delete |main_job| and
5851 // |alternative_job|.
5852 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/true,
5853 /*dns_alpn_h3_job_exists=*/false,
5854 "DNS alpn job must be deleted.");
5855
5856 // Make |main_job| succeed.
5857 MakeMainJobSucceed(/*expect_stream_ready=*/false);
5858
5859 // |main_job| should be cleared.
5860 CheckJobsStatus(/*main_job_exists=*/false, /*alternative_job_exists=*/true,
5861 /*dns_alpn_h3_job_exists=*/false,
5862 "Alternate job must be deleted.");
5863
5864 request_.reset();
5865 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5866 }
5867
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,AllJobsCreatedDnsJobSucceedAltJobSucceedMainJobSucceed)5868 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5869 AllJobsCreatedDnsJobSucceedAltJobSucceedMainJobSucceed) {
5870 PrepareForMainJob();
5871 PrepareForFirstQuicJob();
5872 PrepareForSecondQuicJob();
5873
5874 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
5875
5876 RegisterMockHttpsRecord();
5877
5878 Initialize(HttpRequestInfo());
5879
5880 url::SchemeHostPort server(request_info.url);
5881 AlternativeService alternative_service(kProtoQUIC, "alt.example.org", 443);
5882 SetAlternativeService(request_info, alternative_service);
5883
5884 request_ = CreateJobControllerAndStart(request_info);
5885 // |dns_alpn_h3_job| must be created when a different origin alt service
5886 // was registered.
5887 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/true,
5888 /*dns_alpn_h3_job_exists=*/true,
5889 "All types of jobs are created");
5890
5891 base::HistogramTester histogram_tester;
5892 // Make |dns_alpn_h3_job| succeed.
5893 MakeQuicJobSucceed(1, /*expect_stream_ready=*/true);
5894 histogram_tester.ExpectUniqueSample(
5895 "Net.AlternateProtocolUsage",
5896 ALTERNATE_PROTOCOL_USAGE_DNS_ALPN_H3_JOB_WON_RACE, 1);
5897
5898 // The success of |dns_alpn_h3_job| doesn't delete |main_job| and
5899 // |alternative_job|.
5900 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/true,
5901 /*dns_alpn_h3_job_exists=*/true, "Jobs must not be deleted.");
5902
5903 // Make |alternative_job| succeed.
5904 MakeQuicJobSucceed(0, /*expect_stream_ready=*/false);
5905
5906 // The success of |alternative_job| doesn't delete |main_job| and
5907 // |dns_alpn_h3_job|.
5908 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5909 /*dns_alpn_h3_job_exists=*/true,
5910 "Alternate job must be deleted.");
5911
5912 // Make |main_job| succeed.
5913 MakeMainJobSucceed(/*expect_stream_ready=*/false);
5914
5915 // |main_job| should be cleared.
5916 CheckJobsStatus(/*main_job_exists=*/false, /*alternative_job_exists=*/false,
5917 /*dns_alpn_h3_job_exists=*/true, "Main job must be deleted.");
5918
5919 request_.reset();
5920 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5921 }
5922
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,DnsJobFailOnDefaultNetworkDnsJobFailMainJobSucceed)5923 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5924 DnsJobFailOnDefaultNetworkDnsJobFailMainJobSucceed) {
5925 PrepareForMainJob();
5926 PrepareForFirstQuicJobFailure();
5927
5928 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
5929
5930 RegisterMockHttpsRecord();
5931
5932 Initialize(HttpRequestInfo());
5933 request_ = CreateJobControllerAndStart(request_info);
5934 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5935 /*dns_alpn_h3_job_exists=*/true,
5936 "Main job and DNS ALPN job must be created.");
5937
5938 JobControllerPeer::SetDnsAlpnH3JobFailedOnDefaultNetwork(job_controller_);
5939 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5940 /*dns_alpn_h3_job_exists=*/true, "Jobs must not be deleted.");
5941
5942 base::RunLoop().RunUntilIdle();
5943 base::HistogramTester histogram_tester;
5944 // Make |dns_alpn_h3_job| fail.
5945 quic_data_->Resume();
5946 base::RunLoop().RunUntilIdle();
5947 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5948 /*dns_alpn_h3_job_exists=*/false, "DNS alpn job be deleted.");
5949
5950 // Make |main_job| succeed.
5951 MakeMainJobSucceed(/*expect_stream_ready=*/true);
5952 // Net.AlternateProtocolUsage records
5953 // ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON, when only main job exists.
5954 histogram_tester.ExpectUniqueSample(
5955 "Net.AlternateProtocolUsage", ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON,
5956 1);
5957
5958 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5959 /*dns_alpn_h3_job_exists=*/false,
5960 "DNS alpn job must be deleted.");
5961
5962 request_.reset();
5963 EXPECT_TRUE(IsAlternativeServiceBroken(request_info.url));
5964 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
5965 histogram_tester.ExpectUniqueSample("Net.AlternateServiceForDnsAlpnH3Failed",
5966 -ERR_QUIC_PROTOCOL_ERROR, 1);
5967
5968 // Verify the brokenness is not cleared when the default network changes.
5969 session_->http_server_properties()->OnDefaultNetworkChanged();
5970 EXPECT_TRUE(IsAlternativeServiceBroken(request_info.url));
5971 }
5972
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,DnsJobFailOnDefaultNetworkMainJobSucceedDnsJobSucceed)5973 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
5974 DnsJobFailOnDefaultNetworkMainJobSucceedDnsJobSucceed) {
5975 PrepareForMainJob();
5976 PrepareForFirstQuicJob();
5977
5978 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
5979
5980 RegisterMockHttpsRecord();
5981
5982 Initialize(HttpRequestInfo());
5983 base::HistogramTester histogram_tester;
5984 request_ = CreateJobControllerAndStart(request_info);
5985 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5986 /*dns_alpn_h3_job_exists=*/true,
5987 "Main job and DNS ALPN job must be created.");
5988
5989 JobControllerPeer::SetDnsAlpnH3JobFailedOnDefaultNetwork(job_controller_);
5990 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
5991 /*dns_alpn_h3_job_exists=*/true, "Jobs must not be deleted.");
5992 base::RunLoop().RunUntilIdle();
5993 // Make |main_job| succeed.
5994 MakeMainJobSucceed(/*expect_stream_ready=*/true);
5995 histogram_tester.ExpectUniqueSample(
5996 "Net.AlternateProtocolUsage", ALTERNATE_PROTOCOL_USAGE_MAIN_JOB_WON_RACE,
5997 1);
5998
5999 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
6000 /*dns_alpn_h3_job_exists=*/true,
6001 "DNS alpn job must not be deleted.");
6002
6003 // Make |dns_alpn_h3_job| succeed.
6004 MakeQuicJobSucceed(0, /*expect_stream_ready=*/false);
6005
6006 request_.reset();
6007 histogram_tester.ExpectTotalCount("Net.AlternateServiceForDnsAlpnH3Failed",
6008 0);
6009 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
6010 EXPECT_TRUE(IsAlternativeServiceBroken(request_info.url));
6011
6012 // Verify the brokenness is cleared when the default network changes.
6013 session_->http_server_properties()->OnDefaultNetworkChanged();
6014 EXPECT_FALSE(IsAlternativeServiceBroken(request_info.url));
6015 }
6016
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,DnsJobSucceedMainJobCanceled)6017 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
6018 DnsJobSucceedMainJobCanceled) {
6019 PrepareForMainJob();
6020 PrepareForFirstQuicJob();
6021
6022 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
6023
6024 RegisterMockHttpsRecord();
6025
6026 Initialize(HttpRequestInfo());
6027 request_ = CreateJobControllerAndStart(request_info);
6028 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
6029 /*dns_alpn_h3_job_exists=*/true,
6030 "Main job and DNS ALPN job must be created.");
6031
6032 base::HistogramTester histogram_tester;
6033 // Make |dns_alpn_h3_job| succeed.
6034 MakeQuicJobSucceed(0, /*expect_stream_ready=*/true);
6035 histogram_tester.ExpectUniqueSample(
6036 "Net.AlternateProtocolUsage",
6037 ALTERNATE_PROTOCOL_USAGE_DNS_ALPN_H3_JOB_WON_RACE, 1);
6038
6039 // Main job is canceled.
6040 CheckJobsStatus(/*main_job_exists=*/false, /*alternative_job_exists=*/false,
6041 /*dns_alpn_h3_job_exists=*/true, "Main job must be deleted");
6042
6043 request_.reset();
6044 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
6045 }
6046
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,DnsJobFailOnDefaultNetworkDnsJobSucceedMainJobSucceed)6047 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
6048 DnsJobFailOnDefaultNetworkDnsJobSucceedMainJobSucceed) {
6049 PrepareForMainJob();
6050 PrepareForFirstQuicJob();
6051
6052 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
6053
6054 RegisterMockHttpsRecord();
6055
6056 Initialize(HttpRequestInfo());
6057 request_ = CreateJobControllerAndStart(request_info);
6058 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
6059 /*dns_alpn_h3_job_exists=*/true,
6060 "Main job and DNS ALPN job must be created.");
6061
6062 JobControllerPeer::SetDnsAlpnH3JobFailedOnDefaultNetwork(job_controller_);
6063 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
6064 /*dns_alpn_h3_job_exists=*/true, "Jobs must not be deleted.");
6065
6066 base::HistogramTester histogram_tester;
6067 // Make |dns_alpn_h3_job| succeed.
6068 MakeQuicJobSucceed(0, /*expect_stream_ready=*/true);
6069 histogram_tester.ExpectUniqueSample(
6070 "Net.AlternateProtocolUsage",
6071 ALTERNATE_PROTOCOL_USAGE_DNS_ALPN_H3_JOB_WON_RACE, 1);
6072
6073 // Main job is not canceled, because |dns_alpn_h3_job| has failed on the
6074 // default network.
6075 CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false,
6076 /*dns_alpn_h3_job_exists=*/true,
6077 "Main job must not be deleted.");
6078
6079 // Make |main_job| succeed.
6080 MakeMainJobSucceed(/*expect_stream_ready=*/false);
6081
6082 request_.reset();
6083 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
6084 }
6085
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,PreconnectDnsAlpnH3)6086 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest, PreconnectDnsAlpnH3) {
6087 SetPreconnect();
6088 PrepareForFirstQuicJob();
6089
6090 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
6091
6092 RegisterMockHttpsRecord();
6093
6094 Initialize(HttpRequestInfo());
6095 CreateJobController(request_info);
6096 job_controller_->Preconnect(/*num_streams=*/5);
6097 // Only one job is started.
6098 EXPECT_TRUE(job_controller_->main_job());
6099 EXPECT_FALSE(job_controller_->alternative_job());
6100 EXPECT_EQ(HttpStreamFactory::PRECONNECT_DNS_ALPN_H3,
6101 job_controller_->main_job()->job_type());
6102
6103 MakeQuicJobSucceed(0, /*expect_stream_ready=*/false);
6104
6105 base::RunLoop().RunUntilIdle();
6106 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
6107 }
6108
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,PreconnectAltSvcAvailableActiveSessionAvailable)6109 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
6110 PreconnectAltSvcAvailableActiveSessionAvailable) {
6111 SetPreconnect();
6112 PrepareForFirstQuicJob();
6113
6114 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
6115
6116 RegisterMockHttpsRecord();
6117 Initialize(request_info);
6118
6119 // Register Alt-Svc info.
6120 url::SchemeHostPort server(request_info.url);
6121 AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
6122 SetAlternativeService(request_info, alternative_service);
6123
6124 // Create an active session of require_dns_https_alpn = true.
6125 std::unique_ptr<QuicHttpStream> stream =
6126 ConnectQuicHttpStream(/*alt_destination=*/false,
6127 /*require_dns_https_alpn=*/true);
6128
6129 CreateJobController(request_info);
6130 // Preconnect must succeed using the existing session.
6131 job_controller_->Preconnect(/*num_streams=*/1);
6132 ASSERT_TRUE(job_controller_->main_job());
6133 EXPECT_EQ(HttpStreamFactory::PRECONNECT_DNS_ALPN_H3,
6134 job_controller_->main_job()->job_type());
6135 MakeQuicJobSucceed(0, /*expect_stream_ready=*/false);
6136
6137 base::RunLoop().RunUntilIdle();
6138 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
6139 }
6140
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,PreconnectNoDnsAlpnH3)6141 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest, PreconnectNoDnsAlpnH3) {
6142 EnableOndemandHostResolver();
6143 PrepareForMainJob();
6144 SetPreconnect();
6145
6146 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
6147
6148 Initialize(HttpRequestInfo());
6149 CreateJobController(request_info);
6150 job_controller_->Preconnect(/*num_streams=*/1);
6151 // Only one job is started.
6152 EXPECT_TRUE(job_controller_->main_job());
6153 EXPECT_FALSE(job_controller_->alternative_job());
6154 EXPECT_EQ(HttpStreamFactory::PRECONNECT_DNS_ALPN_H3,
6155 job_controller_->main_job()->job_type());
6156
6157 // Resolve the host resolve request from |dns_alpn_h3_job|.
6158 session_deps_.host_resolver->ResolveAllPending();
6159 base::RunLoop().RunUntilIdle();
6160 EXPECT_EQ(HttpStreamFactory::PRECONNECT,
6161 job_controller_->main_job()->job_type());
6162
6163 base::RunLoop().RunUntilIdle();
6164
6165 // Make |main_job| succeed.
6166 MakeMainJobSucceed(/*expect_stream_ready=*/false);
6167 base::RunLoop().RunUntilIdle();
6168
6169 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
6170 }
6171
6172 // Test that, when an Alt-Svc-based preconnect fails with
6173 // `ERR_DNS_NO_MATCHING_SUPPORTED_ALPN`, the job controller handles it
6174 // correctly. This is a regression test for https://crbug.com/1420202.
6175 //
6176 // In a general HTTPS-RR implementation, this may happen simply because there
6177 // was no A/AAAA route. However, we do not implement HTTPS-RR in full yet (see
6178 // https://crbug.com/1417033), so instead this is only possible in a corner case
6179 // with ECH.
TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,PreconnectAlternateNoDnsAlpn)6180 TEST_F(HttpStreamFactoryJobControllerDnsHttpsAlpnTest,
6181 PreconnectAlternateNoDnsAlpn) {
6182 const char kAlternateHost[] = "alt.example.com";
6183
6184 EnableOndemandHostResolver();
6185 PrepareForMainJob();
6186 SetPreconnect();
6187
6188 // Register a mock HTTPS record where the HTTPS-RR route is only good for h2,
6189 // which is incompatible with Alt-Svc. The A/AAAA route would be compatible,
6190 // but the server supports ECH, so we enable SVCB-reliant mode and reject it.
6191 // As a result, the alternate job will fail.
6192 HostResolverEndpointResult endpoint_result1;
6193 endpoint_result1.ip_endpoints = {IPEndPoint(IPAddress::IPv4Localhost(), 0)};
6194 endpoint_result1.metadata.ech_config_list = {1, 2, 3, 4};
6195 endpoint_result1.metadata.supported_protocol_alpns = {"h2"};
6196 HostResolverEndpointResult endpoint_result2;
6197 endpoint_result2.ip_endpoints = {IPEndPoint(IPAddress::IPv4Localhost(), 0)};
6198 session_deps_.host_resolver->rules()->AddRule(
6199 kAlternateHost,
6200 MockHostResolverBase::RuleResolver::RuleResult(
6201 {endpoint_result1, endpoint_result2}, {kAlternateHost}));
6202
6203 HttpRequestInfo request_info = CreateTestHttpRequestInfo();
6204 Initialize(request_info);
6205 CreateJobController(request_info);
6206
6207 url::SchemeHostPort server(request_info.url);
6208 AlternativeService alternative_service(kProtoQUIC, kAlternateHost, 443);
6209 SetAlternativeService(request_info, alternative_service);
6210
6211 job_controller_->Preconnect(/*num_streams=*/1);
6212 // Only one job is started.
6213 EXPECT_TRUE(job_controller_->main_job());
6214 EXPECT_FALSE(job_controller_->alternative_job());
6215 EXPECT_EQ(HttpStreamFactory::PRECONNECT,
6216 job_controller_->main_job()->job_type());
6217
6218 // Resolve the DNS request.
6219 session_deps_.host_resolver->ResolveAllPending();
6220 base::RunLoop().RunUntilIdle();
6221
6222 // The jobs should have failed. We currently do not try the non-Alt-Svc route
6223 // in preconnects if Alt-Svc failed.
6224 EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_));
6225 }
6226
6227 } // namespace net::test
6228