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