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