1 // Copyright 2012 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.h"
6
7 #include <stdint.h>
8
9 #include <memory>
10 #include <set>
11 #include <string>
12 #include <string_view>
13 #include <tuple>
14 #include <utility>
15 #include <vector>
16
17 #include "base/compiler_specific.h"
18 #include "base/containers/contains.h"
19 #include "base/memory/ptr_util.h"
20 #include "base/no_destructor.h"
21 #include "base/run_loop.h"
22 #include "base/strings/strcat.h"
23 #include "base/test/metrics/histogram_tester.h"
24 #include "base/test/scoped_feature_list.h"
25 #include "build/build_config.h"
26 #include "net/base/completion_once_callback.h"
27 #include "net/base/features.h"
28 #include "net/base/net_errors.h"
29 #include "net/base/network_isolation_key.h"
30 #include "net/base/port_util.h"
31 #include "net/base/privacy_mode.h"
32 #include "net/base/proxy_chain.h"
33 #include "net/base/proxy_server.h"
34 #include "net/base/proxy_string_util.h"
35 #include "net/base/schemeful_site.h"
36 #include "net/base/session_usage.h"
37 #include "net/base/test_completion_callback.h"
38 #include "net/base/test_proxy_delegate.h"
39 #include "net/cert/mock_cert_verifier.h"
40 #include "net/cert/multi_log_ct_verifier.h"
41 #include "net/dns/mock_host_resolver.h"
42 #include "net/dns/public/secure_dns_policy.h"
43 #include "net/http/bidirectional_stream_impl.h"
44 #include "net/http/bidirectional_stream_request_info.h"
45 #include "net/http/http_auth_handler_factory.h"
46 #include "net/http/http_network_session.h"
47 #include "net/http/http_network_session_peer.h"
48 #include "net/http/http_network_transaction.h"
49 #include "net/http/http_proxy_connect_job.h"
50 #include "net/http/http_request_info.h"
51 #include "net/http/http_server_properties.h"
52 #include "net/http/http_stream.h"
53 #include "net/http/transport_security_state.h"
54 #include "net/log/net_log_with_source.h"
55 #include "net/proxy_resolution/configured_proxy_resolution_service.h"
56 #include "net/proxy_resolution/proxy_info.h"
57 #include "net/quic/mock_crypto_client_stream_factory.h"
58 #include "net/quic/mock_quic_context.h"
59 #include "net/quic/mock_quic_data.h"
60 #include "net/quic/quic_http_utils.h"
61 #include "net/quic/quic_session_pool_peer.h"
62 #include "net/quic/quic_test_packet_maker.h"
63 #include "net/quic/quic_test_packet_printer.h"
64 #include "net/socket/client_socket_handle.h"
65 #include "net/socket/client_socket_pool.h"
66 #include "net/socket/connect_job.h"
67 #include "net/socket/mock_client_socket_pool_manager.h"
68 #include "net/socket/next_proto.h"
69 #include "net/socket/socket_tag.h"
70 #include "net/socket/socket_test_util.h"
71 #include "net/socket/socks_connect_job.h"
72 #include "net/socket/ssl_connect_job.h"
73 #include "net/socket/transport_connect_job.h"
74 #include "net/spdy/spdy_session.h"
75 #include "net/spdy/spdy_session_pool.h"
76 #include "net/spdy/spdy_test_util_common.h"
77 #include "net/ssl/ssl_config_service.h"
78 #include "net/ssl/ssl_config_service_defaults.h"
79 #include "net/test/cert_test_util.h"
80 #include "net/test/gtest_util.h"
81 #include "net/test/test_data_directory.h"
82 #include "net/test/test_with_task_environment.h"
83 #include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h"
84 #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
85 #include "net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils.h"
86 #include "net/third_party/quiche/src/quiche/quic/test_tools/mock_random.h"
87 #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h"
88 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
89 #include "net/url_request/static_http_user_agent_settings.h"
90 // This file can be included from net/http even though
91 // it is in net/websockets because it doesn't
92 // introduce any link dependency to net/websockets.
93 #include <optional>
94
95 #include "net/websockets/websocket_handshake_stream_base.h"
96 #include "testing/gmock/include/gmock/gmock.h"
97 #include "testing/gtest/include/gtest/gtest.h"
98 #include "url/gurl.h"
99 #include "url/scheme_host_port.h"
100 #include "url/url_constants.h"
101
102 using ::testing::Contains;
103 using ::testing::ElementsAre;
104 using ::testing::IsEmpty;
105 using ::testing::Key;
106 using ::testing::SizeIs;
107
108 using net::test::IsError;
109 using net::test::IsOk;
110
111 namespace base {
112 class Value;
113 } // namespace base
114
115 namespace net {
116 class BidirectionalStreamImpl;
117 class WebSocketEndpointLockManager;
118 } // namespace net
119
120 namespace net::test {
121
122 namespace {
123
124 class MockWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
125 public:
126 enum StreamType {
127 kStreamTypeBasic,
128 kStreamTypeSpdy,
129 };
130
MockWebSocketHandshakeStream(StreamType type)131 explicit MockWebSocketHandshakeStream(StreamType type) : type_(type) {}
132
133 ~MockWebSocketHandshakeStream() override = default;
134
type() const135 StreamType type() const { return type_; }
136
137 // HttpStream methods
RegisterRequest(const HttpRequestInfo * request_info)138 void RegisterRequest(const HttpRequestInfo* request_info) override {}
InitializeStream(bool can_send_early,RequestPriority priority,const NetLogWithSource & net_log,CompletionOnceCallback callback)139 int InitializeStream(bool can_send_early,
140 RequestPriority priority,
141 const NetLogWithSource& net_log,
142 CompletionOnceCallback callback) override {
143 return ERR_IO_PENDING;
144 }
SendRequest(const HttpRequestHeaders & request_headers,HttpResponseInfo * response,CompletionOnceCallback callback)145 int SendRequest(const HttpRequestHeaders& request_headers,
146 HttpResponseInfo* response,
147 CompletionOnceCallback callback) override {
148 return ERR_IO_PENDING;
149 }
ReadResponseHeaders(CompletionOnceCallback callback)150 int ReadResponseHeaders(CompletionOnceCallback callback) override {
151 return ERR_IO_PENDING;
152 }
ReadResponseBody(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)153 int ReadResponseBody(IOBuffer* buf,
154 int buf_len,
155 CompletionOnceCallback callback) override {
156 return ERR_IO_PENDING;
157 }
Close(bool not_reusable)158 void Close(bool not_reusable) override {}
IsResponseBodyComplete() const159 bool IsResponseBodyComplete() const override { return false; }
IsConnectionReused() const160 bool IsConnectionReused() const override { return false; }
SetConnectionReused()161 void SetConnectionReused() override {}
CanReuseConnection() const162 bool CanReuseConnection() const override { return false; }
GetTotalReceivedBytes() const163 int64_t GetTotalReceivedBytes() const override { return 0; }
GetTotalSentBytes() const164 int64_t GetTotalSentBytes() const override { return 0; }
GetLoadTimingInfo(LoadTimingInfo * load_timing_info) const165 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override {
166 return false;
167 }
GetAlternativeService(AlternativeService * alternative_service) const168 bool GetAlternativeService(
169 AlternativeService* alternative_service) const override {
170 return false;
171 }
GetSSLInfo(SSLInfo * ssl_info)172 void GetSSLInfo(SSLInfo* ssl_info) override {}
GetRemoteEndpoint(IPEndPoint * endpoint)173 int GetRemoteEndpoint(IPEndPoint* endpoint) override {
174 return ERR_UNEXPECTED;
175 }
Drain(HttpNetworkSession * session)176 void Drain(HttpNetworkSession* session) override {}
PopulateNetErrorDetails(NetErrorDetails * details)177 void PopulateNetErrorDetails(NetErrorDetails* details) override { return; }
SetPriority(RequestPriority priority)178 void SetPriority(RequestPriority priority) override {}
RenewStreamForAuth()179 std::unique_ptr<HttpStream> RenewStreamForAuth() override { return nullptr; }
GetDnsAliases() const180 const std::set<std::string>& GetDnsAliases() const override {
181 static const base::NoDestructor<std::set<std::string>> nullset_result;
182 return *nullset_result;
183 }
GetAcceptChViaAlps() const184 std::string_view GetAcceptChViaAlps() const override { return {}; }
185
Upgrade()186 std::unique_ptr<WebSocketStream> Upgrade() override { return nullptr; }
187
CanReadFromStream() const188 bool CanReadFromStream() const override { return true; }
189
GetWeakPtr()190 base::WeakPtr<WebSocketHandshakeStreamBase> GetWeakPtr() override {
191 return weak_ptr_factory_.GetWeakPtr();
192 }
193
194 private:
195 const StreamType type_;
196 base::WeakPtrFactory<MockWebSocketHandshakeStream> weak_ptr_factory_{this};
197 };
198
199 // HttpStreamFactory subclass that can wait until a preconnect is complete.
200 class MockHttpStreamFactoryForPreconnect : public HttpStreamFactory {
201 public:
MockHttpStreamFactoryForPreconnect(HttpNetworkSession * session)202 explicit MockHttpStreamFactoryForPreconnect(HttpNetworkSession* session)
203 : HttpStreamFactory(session) {}
204 ~MockHttpStreamFactoryForPreconnect() override = default;
205
WaitForPreconnects()206 void WaitForPreconnects() {
207 while (!preconnect_done_) {
208 waiting_for_preconnect_ = true;
209 loop_.Run();
210 waiting_for_preconnect_ = false;
211 }
212 }
213
214 private:
215 // HttpStreamFactory methods.
OnPreconnectsCompleteInternal()216 void OnPreconnectsCompleteInternal() override {
217 preconnect_done_ = true;
218 if (waiting_for_preconnect_) {
219 loop_.QuitWhenIdle();
220 }
221 }
222
223 bool preconnect_done_ = false;
224 bool waiting_for_preconnect_ = false;
225 base::RunLoop loop_;
226 };
227
228 class StreamRequestWaiter : public HttpStreamRequest::Delegate {
229 public:
230 StreamRequestWaiter() = default;
231
232 StreamRequestWaiter(const StreamRequestWaiter&) = delete;
233 StreamRequestWaiter& operator=(const StreamRequestWaiter&) = delete;
234
235 // HttpStreamRequest::Delegate
236
OnStreamReady(const ProxyInfo & used_proxy_info,std::unique_ptr<HttpStream> stream)237 void OnStreamReady(const ProxyInfo& used_proxy_info,
238 std::unique_ptr<HttpStream> stream) override {
239 stream_done_ = true;
240 if (loop_) {
241 loop_->Quit();
242 }
243 stream_ = std::move(stream);
244 used_proxy_info_ = used_proxy_info;
245 }
246
OnWebSocketHandshakeStreamReady(const ProxyInfo & used_proxy_info,std::unique_ptr<WebSocketHandshakeStreamBase> stream)247 void OnWebSocketHandshakeStreamReady(
248 const ProxyInfo& used_proxy_info,
249 std::unique_ptr<WebSocketHandshakeStreamBase> stream) override {
250 stream_done_ = true;
251 if (loop_) {
252 loop_->Quit();
253 }
254 websocket_stream_ = std::move(stream);
255 used_proxy_info_ = used_proxy_info;
256 }
257
OnBidirectionalStreamImplReady(const ProxyInfo & used_proxy_info,std::unique_ptr<BidirectionalStreamImpl> stream)258 void OnBidirectionalStreamImplReady(
259 const ProxyInfo& used_proxy_info,
260 std::unique_ptr<BidirectionalStreamImpl> stream) override {
261 stream_done_ = true;
262 if (loop_) {
263 loop_->Quit();
264 }
265 bidirectional_stream_impl_ = std::move(stream);
266 used_proxy_info_ = used_proxy_info;
267 }
268
OnStreamFailed(int status,const NetErrorDetails & net_error_details,const ProxyInfo & used_proxy_info,ResolveErrorInfo resolve_error_info)269 void OnStreamFailed(int status,
270 const NetErrorDetails& net_error_details,
271 const ProxyInfo& used_proxy_info,
272 ResolveErrorInfo resolve_error_info) override {
273 stream_done_ = true;
274 if (loop_) {
275 loop_->Quit();
276 }
277 error_status_ = status;
278 }
279
OnCertificateError(int status,const SSLInfo & ssl_info)280 void OnCertificateError(int status, const SSLInfo& ssl_info) override {}
281
OnNeedsProxyAuth(const HttpResponseInfo & proxy_response,const ProxyInfo & used_proxy_info,HttpAuthController * auth_controller)282 void OnNeedsProxyAuth(const HttpResponseInfo& proxy_response,
283 const ProxyInfo& used_proxy_info,
284 HttpAuthController* auth_controller) override {}
285
OnNeedsClientAuth(SSLCertRequestInfo * cert_info)286 void OnNeedsClientAuth(SSLCertRequestInfo* cert_info) override {}
287
OnQuicBroken()288 void OnQuicBroken() override {}
289
WaitForStream()290 void WaitForStream() {
291 stream_done_ = false;
292 loop_ = std::make_unique<base::RunLoop>();
293 while (!stream_done_) {
294 loop_->Run();
295 }
296 loop_.reset();
297 }
298
used_proxy_info() const299 const ProxyInfo& used_proxy_info() const { return used_proxy_info_; }
300
stream()301 HttpStream* stream() { return stream_.get(); }
302
websocket_stream()303 MockWebSocketHandshakeStream* websocket_stream() {
304 return static_cast<MockWebSocketHandshakeStream*>(websocket_stream_.get());
305 }
306
bidirectional_stream_impl()307 BidirectionalStreamImpl* bidirectional_stream_impl() {
308 return bidirectional_stream_impl_.get();
309 }
310
stream_done() const311 bool stream_done() const { return stream_done_; }
error_status() const312 int error_status() const { return error_status_; }
313
314 protected:
315 bool stream_done_ = false;
316 std::unique_ptr<base::RunLoop> loop_;
317 std::unique_ptr<HttpStream> stream_;
318 std::unique_ptr<WebSocketHandshakeStreamBase> websocket_stream_;
319 std::unique_ptr<BidirectionalStreamImpl> bidirectional_stream_impl_;
320 ProxyInfo used_proxy_info_;
321 int error_status_ = OK;
322 };
323
324 class WebSocketBasicHandshakeStream : public MockWebSocketHandshakeStream {
325 public:
WebSocketBasicHandshakeStream(std::unique_ptr<ClientSocketHandle> connection)326 explicit WebSocketBasicHandshakeStream(
327 std::unique_ptr<ClientSocketHandle> connection)
328 : MockWebSocketHandshakeStream(kStreamTypeBasic),
329 connection_(std::move(connection)) {}
330
~WebSocketBasicHandshakeStream()331 ~WebSocketBasicHandshakeStream() override {
332 connection_->socket()->Disconnect();
333 }
334
connection()335 ClientSocketHandle* connection() { return connection_.get(); }
336
337 private:
338 std::unique_ptr<ClientSocketHandle> connection_;
339 };
340
341 class WebSocketStreamCreateHelper
342 : public WebSocketHandshakeStreamBase::CreateHelper {
343 public:
344 ~WebSocketStreamCreateHelper() override = default;
345
CreateBasicStream(std::unique_ptr<ClientSocketHandle> connection,bool using_proxy,WebSocketEndpointLockManager * websocket_endpoint_lock_manager)346 std::unique_ptr<WebSocketHandshakeStreamBase> CreateBasicStream(
347 std::unique_ptr<ClientSocketHandle> connection,
348 bool using_proxy,
349 WebSocketEndpointLockManager* websocket_endpoint_lock_manager) override {
350 return std::make_unique<WebSocketBasicHandshakeStream>(
351 std::move(connection));
352 }
CreateHttp2Stream(base::WeakPtr<SpdySession> session,std::set<std::string> dns_aliases)353 std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp2Stream(
354 base::WeakPtr<SpdySession> session,
355 std::set<std::string> dns_aliases) override {
356 NOTREACHED();
357 return nullptr;
358 }
CreateHttp3Stream(std::unique_ptr<QuicChromiumClientSession::Handle> session,std::set<std::string> dns_aliases)359 std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp3Stream(
360 std::unique_ptr<QuicChromiumClientSession::Handle> session,
361 std::set<std::string> dns_aliases) override {
362 NOTREACHED();
363 return nullptr;
364 }
365 };
366
367 struct TestCase {
368 int num_streams;
369 bool ssl;
370 };
371
372 TestCase kTests[] = {
373 {1, false},
374 {2, false},
375 {1, true},
376 {2, true},
377 };
378
PreconnectHelperForURL(int num_streams,const GURL & url,NetworkAnonymizationKey network_anonymization_key,SecureDnsPolicy secure_dns_policy,HttpNetworkSession * session)379 void PreconnectHelperForURL(int num_streams,
380 const GURL& url,
381 NetworkAnonymizationKey network_anonymization_key,
382 SecureDnsPolicy secure_dns_policy,
383 HttpNetworkSession* session) {
384 HttpNetworkSessionPeer peer(session);
385 auto mock_factory =
386 std::make_unique<MockHttpStreamFactoryForPreconnect>(session);
387 auto* mock_factory_ptr = mock_factory.get();
388 peer.SetHttpStreamFactory(std::move(mock_factory));
389
390 HttpRequestInfo request;
391 request.method = "GET";
392 request.url = url;
393 request.load_flags = 0;
394 request.network_anonymization_key = network_anonymization_key;
395 request.secure_dns_policy = secure_dns_policy;
396 request.traffic_annotation =
397 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
398
399 session->http_stream_factory()->PreconnectStreams(num_streams, request);
400 mock_factory_ptr->WaitForPreconnects();
401 }
402
PreconnectHelper(const TestCase & test,HttpNetworkSession * session)403 void PreconnectHelper(const TestCase& test, HttpNetworkSession* session) {
404 GURL url =
405 test.ssl ? GURL("https://www.google.com") : GURL("http://www.google.com");
406 PreconnectHelperForURL(test.num_streams, url, NetworkAnonymizationKey(),
407 SecureDnsPolicy::kAllow, session);
408 }
409
GetGroupId(const TestCase & test)410 ClientSocketPool::GroupId GetGroupId(const TestCase& test) {
411 if (test.ssl) {
412 return ClientSocketPool::GroupId(
413 url::SchemeHostPort(url::kHttpsScheme, "www.google.com", 443),
414 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
415 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false);
416 }
417 return ClientSocketPool::GroupId(
418 url::SchemeHostPort(url::kHttpScheme, "www.google.com", 80),
419 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
420 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false);
421 }
422
423 class CapturePreconnectsTransportSocketPool : public TransportClientSocketPool {
424 public:
CapturePreconnectsTransportSocketPool(const CommonConnectJobParams * common_connect_job_params)425 explicit CapturePreconnectsTransportSocketPool(
426 const CommonConnectJobParams* common_connect_job_params)
427 : TransportClientSocketPool(/*max_sockets=*/0,
428 /*max_sockets_per_group=*/0,
429 base::TimeDelta(),
430 ProxyChain::Direct(),
431 /*is_for_websockets=*/false,
432 common_connect_job_params) {}
433
last_num_streams() const434 int last_num_streams() const { return last_num_streams_; }
last_group_id() const435 const ClientSocketPool::GroupId& last_group_id() const {
436 return last_group_id_;
437 }
438
439 // Resets |last_num_streams_| and |last_group_id_| default values.
reset()440 void reset() {
441 last_num_streams_ = -1;
442 // Group ID that shouldn't match much.
443 last_group_id_ = ClientSocketPool::GroupId(
444 url::SchemeHostPort(url::kHttpsScheme,
445 "unexpected.to.conflict.with.anything.test", 9999),
446 PrivacyMode::PRIVACY_MODE_ENABLED, NetworkAnonymizationKey(),
447 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false);
448 }
449
RequestSocket(const ClientSocketPool::GroupId & group_id,scoped_refptr<ClientSocketPool::SocketParams> socket_params,const std::optional<NetworkTrafficAnnotationTag> & proxy_annotation_tag,RequestPriority priority,const SocketTag & socket_tag,ClientSocketPool::RespectLimits respect_limits,ClientSocketHandle * handle,CompletionOnceCallback callback,const ClientSocketPool::ProxyAuthCallback & proxy_auth_callback,const NetLogWithSource & net_log)450 int RequestSocket(
451 const ClientSocketPool::GroupId& group_id,
452 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
453 const std::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
454 RequestPriority priority,
455 const SocketTag& socket_tag,
456 ClientSocketPool::RespectLimits respect_limits,
457 ClientSocketHandle* handle,
458 CompletionOnceCallback callback,
459 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
460 const NetLogWithSource& net_log) override {
461 ADD_FAILURE();
462 return ERR_UNEXPECTED;
463 }
464
RequestSockets(const ClientSocketPool::GroupId & group_id,scoped_refptr<ClientSocketPool::SocketParams> socket_params,const std::optional<NetworkTrafficAnnotationTag> & proxy_annotation_tag,int num_sockets,CompletionOnceCallback callback,const NetLogWithSource & net_log)465 int RequestSockets(
466 const ClientSocketPool::GroupId& group_id,
467 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
468 const std::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
469 int num_sockets,
470 CompletionOnceCallback callback,
471 const NetLogWithSource& net_log) override {
472 last_num_streams_ = num_sockets;
473 last_group_id_ = group_id;
474 return OK;
475 }
476
CancelRequest(const ClientSocketPool::GroupId & group_id,ClientSocketHandle * handle,bool cancel_connect_job)477 void CancelRequest(const ClientSocketPool::GroupId& group_id,
478 ClientSocketHandle* handle,
479 bool cancel_connect_job) override {
480 ADD_FAILURE();
481 }
ReleaseSocket(const ClientSocketPool::GroupId & group_id,std::unique_ptr<StreamSocket> socket,int64_t generation)482 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
483 std::unique_ptr<StreamSocket> socket,
484 int64_t generation) override {
485 ADD_FAILURE();
486 }
CloseIdleSockets(const char * net_log_reason_utf8)487 void CloseIdleSockets(const char* net_log_reason_utf8) override {
488 ADD_FAILURE();
489 }
IdleSocketCount() const490 int IdleSocketCount() const override {
491 ADD_FAILURE();
492 return 0;
493 }
IdleSocketCountInGroup(const ClientSocketPool::GroupId & group_id) const494 size_t IdleSocketCountInGroup(
495 const ClientSocketPool::GroupId& group_id) const override {
496 ADD_FAILURE();
497 return 0;
498 }
GetLoadState(const ClientSocketPool::GroupId & group_id,const ClientSocketHandle * handle) const499 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
500 const ClientSocketHandle* handle) const override {
501 ADD_FAILURE();
502 return LOAD_STATE_IDLE;
503 }
504
505 private:
506 int last_num_streams_ = -1;
507 ClientSocketPool::GroupId last_group_id_;
508 };
509
510 using HttpStreamFactoryTest = TestWithTaskEnvironment;
511
TEST_F(HttpStreamFactoryTest,PreconnectDirect)512 TEST_F(HttpStreamFactoryTest, PreconnectDirect) {
513 for (const auto& test : kTests) {
514 SpdySessionDependencies session_deps(
515 ConfiguredProxyResolutionService::CreateDirect());
516 std::unique_ptr<HttpNetworkSession> session(
517 SpdySessionDependencies::SpdyCreateSession(&session_deps));
518 HttpNetworkSessionPeer peer(session.get());
519 CommonConnectJobParams common_connect_job_params =
520 session->CreateCommonConnectJobParams();
521 std::unique_ptr<CapturePreconnectsTransportSocketPool>
522 owned_transport_conn_pool =
523 std::make_unique<CapturePreconnectsTransportSocketPool>(
524 &common_connect_job_params);
525 CapturePreconnectsTransportSocketPool* transport_conn_pool =
526 owned_transport_conn_pool.get();
527 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
528 mock_pool_manager->SetSocketPool(ProxyChain::Direct(),
529 std::move(owned_transport_conn_pool));
530 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
531 PreconnectHelper(test, session.get());
532 EXPECT_EQ(test.num_streams, transport_conn_pool->last_num_streams());
533 EXPECT_EQ(GetGroupId(test), transport_conn_pool->last_group_id());
534 }
535 }
536
TEST_F(HttpStreamFactoryTest,PreconnectHttpProxy)537 TEST_F(HttpStreamFactoryTest, PreconnectHttpProxy) {
538 for (const auto& test : kTests) {
539 SpdySessionDependencies session_deps(
540 ConfiguredProxyResolutionService::CreateFixedForTest(
541 "http_proxy", TRAFFIC_ANNOTATION_FOR_TESTS));
542 std::unique_ptr<HttpNetworkSession> session(
543 SpdySessionDependencies::SpdyCreateSession(&session_deps));
544 HttpNetworkSessionPeer peer(session.get());
545 ProxyChain proxy_chain(ProxyServer::SCHEME_HTTP,
546 HostPortPair("http_proxy", 80));
547 CommonConnectJobParams common_connect_job_params =
548 session->CreateCommonConnectJobParams();
549
550 auto http_proxy_pool =
551 std::make_unique<CapturePreconnectsTransportSocketPool>(
552 &common_connect_job_params);
553 auto* http_proxy_pool_ptr = http_proxy_pool.get();
554 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
555 mock_pool_manager->SetSocketPool(proxy_chain, std::move(http_proxy_pool));
556 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
557 PreconnectHelper(test, session.get());
558 EXPECT_EQ(test.num_streams, http_proxy_pool_ptr->last_num_streams());
559 EXPECT_EQ(GetGroupId(test), http_proxy_pool_ptr->last_group_id());
560 }
561 }
562
TEST_F(HttpStreamFactoryTest,PreconnectSocksProxy)563 TEST_F(HttpStreamFactoryTest, PreconnectSocksProxy) {
564 for (const auto& test : kTests) {
565 SpdySessionDependencies session_deps(
566 ConfiguredProxyResolutionService::CreateFixedForTest(
567 "socks4://socks_proxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS));
568 std::unique_ptr<HttpNetworkSession> session(
569 SpdySessionDependencies::SpdyCreateSession(&session_deps));
570 HttpNetworkSessionPeer peer(session.get());
571 ProxyChain proxy_chain(ProxyServer::SCHEME_SOCKS4,
572 HostPortPair("socks_proxy", 1080));
573 CommonConnectJobParams common_connect_job_params =
574 session->CreateCommonConnectJobParams();
575 auto socks_proxy_pool =
576 std::make_unique<CapturePreconnectsTransportSocketPool>(
577 &common_connect_job_params);
578 auto* socks_proxy_pool_ptr = socks_proxy_pool.get();
579 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
580 mock_pool_manager->SetSocketPool(proxy_chain, std::move(socks_proxy_pool));
581 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
582 PreconnectHelper(test, session.get());
583 EXPECT_EQ(test.num_streams, socks_proxy_pool_ptr->last_num_streams());
584 EXPECT_EQ(GetGroupId(test), socks_proxy_pool_ptr->last_group_id());
585 }
586 }
587
TEST_F(HttpStreamFactoryTest,PreconnectDirectWithExistingSpdySession)588 TEST_F(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) {
589 for (const auto& test : kTests) {
590 SpdySessionDependencies session_deps(
591 ConfiguredProxyResolutionService::CreateDirect());
592 std::unique_ptr<HttpNetworkSession> session(
593 SpdySessionDependencies::SpdyCreateSession(&session_deps));
594 HttpNetworkSessionPeer peer(session.get());
595
596 // Put a SpdySession in the pool.
597 HostPortPair host_port_pair("www.google.com", 443);
598 SpdySessionKey key(host_port_pair, PRIVACY_MODE_DISABLED,
599 ProxyChain::Direct(), SessionUsage::kDestination,
600 SocketTag(), NetworkAnonymizationKey(),
601 SecureDnsPolicy::kAllow,
602 /*disable_cert_verification_network_fetches=*/false);
603 std::ignore = CreateFakeSpdySession(session->spdy_session_pool(), key);
604
605 CommonConnectJobParams common_connect_job_params =
606 session->CreateCommonConnectJobParams();
607 std::unique_ptr<CapturePreconnectsTransportSocketPool>
608 owned_transport_conn_pool =
609 std::make_unique<CapturePreconnectsTransportSocketPool>(
610 &common_connect_job_params);
611 CapturePreconnectsTransportSocketPool* transport_conn_pool =
612 owned_transport_conn_pool.get();
613 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
614 mock_pool_manager->SetSocketPool(ProxyChain::Direct(),
615 std::move(owned_transport_conn_pool));
616 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
617 PreconnectHelper(test, session.get());
618 // We shouldn't be preconnecting if we have an existing session, which is
619 // the case for https://www.google.com.
620 if (test.ssl) {
621 EXPECT_EQ(-1, transport_conn_pool->last_num_streams());
622 } else {
623 EXPECT_EQ(test.num_streams, transport_conn_pool->last_num_streams());
624 }
625 }
626 }
627
628 // Verify that preconnects to unsafe ports are cancelled before they reach
629 // the SocketPool.
TEST_F(HttpStreamFactoryTest,PreconnectUnsafePort)630 TEST_F(HttpStreamFactoryTest, PreconnectUnsafePort) {
631 ASSERT_FALSE(IsPortAllowedForScheme(7, "http"));
632
633 SpdySessionDependencies session_deps(
634 ConfiguredProxyResolutionService::CreateDirect());
635 std::unique_ptr<HttpNetworkSession> session(
636 SpdySessionDependencies::SpdyCreateSession(&session_deps));
637 HttpNetworkSessionPeer peer(session.get());
638 CommonConnectJobParams common_connect_job_params =
639 session->CreateCommonConnectJobParams();
640 std::unique_ptr<CapturePreconnectsTransportSocketPool>
641 owned_transport_conn_pool =
642 std::make_unique<CapturePreconnectsTransportSocketPool>(
643 &common_connect_job_params);
644 CapturePreconnectsTransportSocketPool* transport_conn_pool =
645 owned_transport_conn_pool.get();
646 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
647 mock_pool_manager->SetSocketPool(ProxyChain::Direct(),
648 std::move(owned_transport_conn_pool));
649 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
650
651 PreconnectHelperForURL(1, GURL("http://www.google.com:7"),
652 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
653 session.get());
654 EXPECT_EQ(-1, transport_conn_pool->last_num_streams());
655 }
656
657 // Verify that preconnects use the specified NetworkAnonymizationKey.
TEST_F(HttpStreamFactoryTest,PreconnectNetworkIsolationKey)658 TEST_F(HttpStreamFactoryTest, PreconnectNetworkIsolationKey) {
659 base::test::ScopedFeatureList feature_list;
660 feature_list.InitAndEnableFeature(
661 features::kPartitionConnectionsByNetworkIsolationKey);
662
663 SpdySessionDependencies session_deps(
664 ConfiguredProxyResolutionService::CreateDirect());
665 std::unique_ptr<HttpNetworkSession> session(
666 SpdySessionDependencies::SpdyCreateSession(&session_deps));
667 HttpNetworkSessionPeer peer(session.get());
668 CommonConnectJobParams common_connect_job_params =
669 session->CreateCommonConnectJobParams();
670 std::unique_ptr<CapturePreconnectsTransportSocketPool>
671 owned_transport_conn_pool =
672 std::make_unique<CapturePreconnectsTransportSocketPool>(
673 &common_connect_job_params);
674 CapturePreconnectsTransportSocketPool* transport_conn_pool =
675 owned_transport_conn_pool.get();
676 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
677 mock_pool_manager->SetSocketPool(ProxyChain::Direct(),
678 std::move(owned_transport_conn_pool));
679 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
680
681 const GURL kURL("http://foo.test/");
682 SchemefulSite kSiteFoo(GURL("http://foo.test"));
683 SchemefulSite kSiteBar(GURL("http://bar.test"));
684 const auto kKey1 = NetworkAnonymizationKey::CreateSameSite(kSiteFoo);
685 const auto kKey2 = NetworkAnonymizationKey::CreateSameSite(kSiteBar);
686 PreconnectHelperForURL(1, kURL, kKey1, SecureDnsPolicy::kAllow,
687 session.get());
688 EXPECT_EQ(1, transport_conn_pool->last_num_streams());
689 EXPECT_EQ(kKey1,
690 transport_conn_pool->last_group_id().network_anonymization_key());
691
692 PreconnectHelperForURL(2, kURL, kKey2, SecureDnsPolicy::kAllow,
693 session.get());
694 EXPECT_EQ(2, transport_conn_pool->last_num_streams());
695 EXPECT_EQ(kKey2,
696 transport_conn_pool->last_group_id().network_anonymization_key());
697 }
698
699 // Verify that preconnects use the specified Secure DNS Tag.
TEST_F(HttpStreamFactoryTest,PreconnectDisableSecureDns)700 TEST_F(HttpStreamFactoryTest, PreconnectDisableSecureDns) {
701 SpdySessionDependencies session_deps(
702 ConfiguredProxyResolutionService::CreateDirect());
703 std::unique_ptr<HttpNetworkSession> session(
704 SpdySessionDependencies::SpdyCreateSession(&session_deps));
705 HttpNetworkSessionPeer peer(session.get());
706 CommonConnectJobParams common_connect_job_params =
707 session->CreateCommonConnectJobParams();
708 std::unique_ptr<CapturePreconnectsTransportSocketPool>
709 owned_transport_conn_pool =
710 std::make_unique<CapturePreconnectsTransportSocketPool>(
711 &common_connect_job_params);
712 CapturePreconnectsTransportSocketPool* transport_conn_pool =
713 owned_transport_conn_pool.get();
714 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
715 mock_pool_manager->SetSocketPool(ProxyChain::Direct(),
716 std::move(owned_transport_conn_pool));
717 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
718
719 const GURL kURL("http://foo.test/");
720 SchemefulSite kSiteFoo(GURL("http://foo.test"));
721 SchemefulSite kSiteBar(GURL("http://bar.test"));
722 PreconnectHelperForURL(1, kURL, NetworkAnonymizationKey(),
723 SecureDnsPolicy::kAllow, session.get());
724 EXPECT_EQ(1, transport_conn_pool->last_num_streams());
725 EXPECT_EQ(SecureDnsPolicy::kAllow,
726 transport_conn_pool->last_group_id().secure_dns_policy());
727
728 PreconnectHelperForURL(2, kURL, NetworkAnonymizationKey(),
729 SecureDnsPolicy::kDisable, session.get());
730 EXPECT_EQ(2, transport_conn_pool->last_num_streams());
731 EXPECT_EQ(SecureDnsPolicy::kDisable,
732 transport_conn_pool->last_group_id().secure_dns_policy());
733 }
734
TEST_F(HttpStreamFactoryTest,JobNotifiesProxy)735 TEST_F(HttpStreamFactoryTest, JobNotifiesProxy) {
736 const char* kProxyString = "PROXY bad:99; PROXY maybe:80; DIRECT";
737 SpdySessionDependencies session_deps(
738 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
739 kProxyString, TRAFFIC_ANNOTATION_FOR_TESTS));
740
741 // First connection attempt fails
742 StaticSocketDataProvider socket_data1;
743 socket_data1.set_connect_data(MockConnect(ASYNC, ERR_ADDRESS_UNREACHABLE));
744 session_deps.socket_factory->AddSocketDataProvider(&socket_data1);
745
746 // Second connection attempt succeeds
747 StaticSocketDataProvider socket_data2;
748 socket_data2.set_connect_data(MockConnect(ASYNC, OK));
749 session_deps.socket_factory->AddSocketDataProvider(&socket_data2);
750
751 std::unique_ptr<HttpNetworkSession> session(
752 SpdySessionDependencies::SpdyCreateSession(&session_deps));
753
754 // Now request a stream. It should succeed using the second proxy in the
755 // list.
756 HttpRequestInfo request_info;
757 request_info.method = "GET";
758 request_info.url = GURL("http://www.google.com");
759 request_info.traffic_annotation =
760 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
761
762 StreamRequestWaiter waiter;
763 std::unique_ptr<HttpStreamRequest> request(
764 session->http_stream_factory()->RequestStream(
765 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
766 /* enable_ip_based_pooling = */ true,
767 /* enable_alternative_services = */ true, NetLogWithSource()));
768 waiter.WaitForStream();
769
770 // The proxy that failed should now be known to the proxy_resolution_service
771 // as bad.
772 const ProxyRetryInfoMap& retry_info =
773 session->proxy_resolution_service()->proxy_retry_info();
774 EXPECT_EQ(1u, retry_info.size());
775 auto iter = retry_info.find(
776 ProxyChain(ProxyUriToProxyServer("bad:99", ProxyServer::SCHEME_HTTP)));
777 EXPECT_TRUE(iter != retry_info.end());
778 }
779
780 // This test requests a stream for an https:// URL using an HTTP proxy.
781 // The proxy will fail to establish a tunnel via connect, and the resolved
782 // proxy list includes a fallback to DIRECT.
783 //
784 // The expected behavior is that proxy fallback does NOT occur, even though the
785 // request might work using the fallback. This is a regression test for
786 // https://crbug.com/680837.
TEST_F(HttpStreamFactoryTest,NoProxyFallbackOnTunnelFail)787 TEST_F(HttpStreamFactoryTest, NoProxyFallbackOnTunnelFail) {
788 const char* kProxyString = "PROXY bad:99; DIRECT";
789 SpdySessionDependencies session_deps(
790 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
791 kProxyString, TRAFFIC_ANNOTATION_FOR_TESTS));
792
793 // A 404 in response to a CONNECT will trigger
794 // ERR_TUNNEL_CONNECTION_FAILED.
795 MockRead data_reads[] = {
796 MockRead("HTTP/1.1 404 Not Found\r\n\r\n"),
797 MockRead(SYNCHRONOUS, OK),
798 };
799
800 // Simulate a failure during CONNECT to bad:99.
801 StaticSocketDataProvider socket_data1(data_reads, base::span<MockWrite>());
802 socket_data1.set_connect_data(MockConnect(SYNCHRONOUS, OK));
803 session_deps.socket_factory->AddSocketDataProvider(&socket_data1);
804
805 std::unique_ptr<HttpNetworkSession> session(
806 SpdySessionDependencies::SpdyCreateSession(&session_deps));
807
808 // Request a stream for an https:// URL. The exact URL doesn't matter for
809 // this test, since it mocks a failure immediately when establishing a
810 // tunnel through the proxy.
811 HttpRequestInfo request_info;
812 request_info.method = "GET";
813 request_info.url = GURL("https://www.google.com");
814 request_info.traffic_annotation =
815 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
816
817 StreamRequestWaiter waiter;
818 std::unique_ptr<HttpStreamRequest> request(
819 session->http_stream_factory()->RequestStream(
820 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
821 /* enable_ip_based_pooling = */ true,
822 /* enable_alternative_services = */ true, NetLogWithSource()));
823 waiter.WaitForStream();
824
825 // The stream should have failed, since the proxy server failed to
826 // establish a tunnel.
827 ASSERT_THAT(waiter.error_status(), IsError(ERR_TUNNEL_CONNECTION_FAILED));
828
829 // The proxy should NOT have been marked as bad.
830 const ProxyRetryInfoMap& retry_info =
831 session->proxy_resolution_service()->proxy_retry_info();
832 EXPECT_EQ(0u, retry_info.size());
833 }
834
835 // List of errors that are used in the tests related to QUIC proxy.
836 const int quic_proxy_test_mock_errors[] = {
837 ERR_PROXY_CONNECTION_FAILED,
838 ERR_NAME_NOT_RESOLVED,
839 ERR_ADDRESS_UNREACHABLE,
840 ERR_CONNECTION_CLOSED,
841 ERR_CONNECTION_TIMED_OUT,
842 ERR_CONNECTION_RESET,
843 ERR_CONNECTION_REFUSED,
844 ERR_CONNECTION_ABORTED,
845 ERR_TIMED_OUT,
846 ERR_SOCKS_CONNECTION_FAILED,
847 ERR_PROXY_CERTIFICATE_INVALID,
848 ERR_QUIC_PROTOCOL_ERROR,
849 ERR_QUIC_HANDSHAKE_FAILED,
850 ERR_SSL_PROTOCOL_ERROR,
851 ERR_MSG_TOO_BIG,
852 };
853
854 // Tests that a bad QUIC proxy is added to the list of bad proxies.
TEST_F(HttpStreamFactoryTest,QuicProxyMarkedAsBad)855 TEST_F(HttpStreamFactoryTest, QuicProxyMarkedAsBad) {
856 for (int quic_proxy_test_mock_error : quic_proxy_test_mock_errors) {
857 auto quic_proxy_chain =
858 ProxyChain::ForIpProtection({ProxyServer::FromSchemeHostAndPort(
859 ProxyServer::SCHEME_QUIC, "bad", 99)});
860 std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
861 ConfiguredProxyResolutionService::CreateFixedFromProxyChainsForTest(
862 {quic_proxy_chain, ProxyChain::Direct()},
863 TRAFFIC_ANNOTATION_FOR_TESTS);
864
865 HttpNetworkSessionParams session_params;
866 session_params.enable_quic = true;
867
868 HttpNetworkSessionContext session_context;
869 SSLConfigServiceDefaults ssl_config_service;
870 HttpServerProperties http_server_properties;
871 MockClientSocketFactory socket_factory;
872 session_context.client_socket_factory = &socket_factory;
873 MockHostResolver host_resolver;
874 session_context.host_resolver = &host_resolver;
875 MockCertVerifier cert_verifier;
876 session_context.cert_verifier = &cert_verifier;
877 TransportSecurityState transport_security_state;
878 session_context.transport_security_state = &transport_security_state;
879 QuicContext quic_context;
880 session_context.proxy_resolution_service = proxy_resolution_service.get();
881 session_context.ssl_config_service = &ssl_config_service;
882 session_context.http_server_properties = &http_server_properties;
883 session_context.quic_context = &quic_context;
884
885 host_resolver.rules()->AddRule("www.google.com", "2.3.4.5");
886 host_resolver.rules()->AddRule("bad", "1.2.3.4");
887
888 auto session =
889 std::make_unique<HttpNetworkSession>(session_params, session_context);
890 session->quic_session_pool()->set_is_quic_known_to_work_on_current_network(
891 true);
892
893 StaticSocketDataProvider socket_data1;
894 socket_data1.set_connect_data(
895 MockConnect(ASYNC, quic_proxy_test_mock_error));
896 socket_factory.AddSocketDataProvider(&socket_data1);
897
898 // Second connection attempt succeeds.
899 StaticSocketDataProvider socket_data2;
900 socket_data2.set_connect_data(MockConnect(ASYNC, OK));
901 socket_factory.AddSocketDataProvider(&socket_data2);
902
903 // Now request a stream. It should succeed using the second proxy in the
904 // list.
905 HttpRequestInfo request_info;
906 request_info.method = "GET";
907 request_info.url = GURL("http://www.google.com");
908 request_info.traffic_annotation =
909 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
910
911 StreamRequestWaiter waiter;
912 std::unique_ptr<HttpStreamRequest> request(
913 session->http_stream_factory()->RequestStream(
914 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
915 &waiter, /* enable_ip_based_pooling = */ true,
916 /* enable_alternative_services = */ true, NetLogWithSource()));
917 waiter.WaitForStream();
918
919 // The proxy that failed should now be known to the
920 // proxy_resolution_service as bad.
921 const ProxyRetryInfoMap& retry_info =
922 session->proxy_resolution_service()->proxy_retry_info();
923 EXPECT_EQ(1u, retry_info.size()) << quic_proxy_test_mock_error;
924 EXPECT_TRUE(waiter.used_proxy_info().is_direct());
925
926 auto iter = retry_info.find(quic_proxy_chain);
927 EXPECT_TRUE(iter != retry_info.end()) << quic_proxy_test_mock_error;
928 }
929 }
930
931 // BidirectionalStreamImpl::Delegate to wait until response headers are
932 // received.
933 class TestBidirectionalDelegate : public BidirectionalStreamImpl::Delegate {
934 public:
WaitUntilDone()935 void WaitUntilDone() { loop_.Run(); }
936
response_headers() const937 const spdy::Http2HeaderBlock& response_headers() const {
938 return response_headers_;
939 }
940
941 private:
OnStreamReady(bool request_headers_sent)942 void OnStreamReady(bool request_headers_sent) override {}
OnHeadersReceived(const spdy::Http2HeaderBlock & response_headers)943 void OnHeadersReceived(
944 const spdy::Http2HeaderBlock& response_headers) override {
945 response_headers_ = response_headers.Clone();
946 loop_.Quit();
947 }
OnDataRead(int bytes_read)948 void OnDataRead(int bytes_read) override { NOTREACHED(); }
OnDataSent()949 void OnDataSent() override { NOTREACHED(); }
OnTrailersReceived(const spdy::Http2HeaderBlock & trailers)950 void OnTrailersReceived(const spdy::Http2HeaderBlock& trailers) override {
951 NOTREACHED();
952 }
OnFailed(int error)953 void OnFailed(int error) override { NOTREACHED(); }
954 base::RunLoop loop_;
955 spdy::Http2HeaderBlock response_headers_;
956 };
957
958 } // namespace
959
TEST_F(HttpStreamFactoryTest,UsePreConnectIfNoZeroRTT)960 TEST_F(HttpStreamFactoryTest, UsePreConnectIfNoZeroRTT) {
961 for (int num_streams = 1; num_streams < 3; ++num_streams) {
962 GURL url = GURL("https://www.google.com");
963
964 SpdySessionDependencies session_deps(
965 ConfiguredProxyResolutionService::CreateFixedFromProxyChainsForTest(
966 {ProxyChain::ForIpProtection({ProxyServer::FromSchemeHostAndPort(
967 ProxyServer::SCHEME_QUIC, "quic_proxy", 443)})},
968 TRAFFIC_ANNOTATION_FOR_TESTS));
969
970 // Setup params to disable preconnect, but QUIC doesn't 0RTT.
971 HttpNetworkSessionParams session_params =
972 SpdySessionDependencies::CreateSessionParams(&session_deps);
973 session_params.enable_quic = true;
974
975 // Set up QUIC as alternative_service.
976 HttpServerProperties http_server_properties;
977 const AlternativeService alternative_service(kProtoQUIC, url.host().c_str(),
978 url.IntPort());
979 base::Time expiration = base::Time::Now() + base::Days(1);
980 HostPortPair host_port_pair(alternative_service.host_port_pair());
981 url::SchemeHostPort server("https", host_port_pair.host(),
982 host_port_pair.port());
983 http_server_properties.SetQuicAlternativeService(
984 server, NetworkAnonymizationKey(), alternative_service, expiration,
985 DefaultSupportedQuicVersions());
986
987 HttpNetworkSessionContext session_context =
988 SpdySessionDependencies::CreateSessionContext(&session_deps);
989 session_context.http_server_properties = &http_server_properties;
990
991 auto session =
992 std::make_unique<HttpNetworkSession>(session_params, session_context);
993 HttpNetworkSessionPeer peer(session.get());
994 ProxyChain proxy_chain =
995 ProxyChain::ForIpProtection({ProxyServer::FromSchemeHostAndPort(
996 ProxyServer::SCHEME_QUIC, "quic_proxy", 443)});
997 CommonConnectJobParams common_connect_job_params =
998 session->CreateCommonConnectJobParams();
999 auto http_proxy_pool =
1000 std::make_unique<CapturePreconnectsTransportSocketPool>(
1001 &common_connect_job_params);
1002 auto* http_proxy_pool_ptr = http_proxy_pool.get();
1003 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
1004 mock_pool_manager->SetSocketPool(proxy_chain, std::move(http_proxy_pool));
1005 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
1006 PreconnectHelperForURL(num_streams, url, NetworkAnonymizationKey(),
1007 SecureDnsPolicy::kAllow, session.get());
1008 EXPECT_EQ(num_streams, http_proxy_pool_ptr->last_num_streams());
1009 }
1010 }
1011
1012 namespace {
1013
1014 // Return count of distinct groups in given socket pool.
GetSocketPoolGroupCount(ClientSocketPool * pool)1015 int GetSocketPoolGroupCount(ClientSocketPool* pool) {
1016 int count = 0;
1017 base::Value dict = pool->GetInfoAsValue("", "");
1018 EXPECT_TRUE(dict.is_dict());
1019 const base::Value::Dict* groups = dict.GetDict().FindDict("groups");
1020 if (groups) {
1021 count = groups->size();
1022 }
1023 return count;
1024 }
1025
1026 // Return count of distinct spdy sessions.
GetSpdySessionCount(HttpNetworkSession * session)1027 int GetSpdySessionCount(HttpNetworkSession* session) {
1028 std::unique_ptr<base::Value> value(
1029 session->spdy_session_pool()->SpdySessionPoolInfoToValue());
1030 if (!value || !value->is_list()) {
1031 return -1;
1032 }
1033 return value->GetList().size();
1034 }
1035
1036 // Return count of sockets handed out by a given socket pool.
GetHandedOutSocketCount(ClientSocketPool * pool)1037 int GetHandedOutSocketCount(ClientSocketPool* pool) {
1038 base::Value dict = pool->GetInfoAsValue("", "");
1039 EXPECT_TRUE(dict.is_dict());
1040 return dict.GetDict().FindInt("handed_out_socket_count").value_or(-1);
1041 }
1042
1043 // Return count of distinct QUIC sessions.
GetQuicSessionCount(HttpNetworkSession * session)1044 int GetQuicSessionCount(HttpNetworkSession* session) {
1045 base::Value dict(session->QuicInfoToValue());
1046 base::Value::List* session_list = dict.GetDict().FindList("sessions");
1047 if (!session_list) {
1048 return -1;
1049 }
1050 return session_list->size();
1051 }
1052
TEST_F(HttpStreamFactoryTest,PrivacyModeUsesDifferentSocketPoolGroup)1053 TEST_F(HttpStreamFactoryTest, PrivacyModeUsesDifferentSocketPoolGroup) {
1054 SpdySessionDependencies session_deps(
1055 ConfiguredProxyResolutionService::CreateDirect());
1056
1057 StaticSocketDataProvider socket_data_1;
1058 socket_data_1.set_connect_data(MockConnect(ASYNC, OK));
1059 session_deps.socket_factory->AddSocketDataProvider(&socket_data_1);
1060 StaticSocketDataProvider socket_data_2;
1061 socket_data_2.set_connect_data(MockConnect(ASYNC, OK));
1062 session_deps.socket_factory->AddSocketDataProvider(&socket_data_2);
1063 StaticSocketDataProvider socket_data_3;
1064 socket_data_3.set_connect_data(MockConnect(ASYNC, OK));
1065 session_deps.socket_factory->AddSocketDataProvider(&socket_data_3);
1066
1067 SSLSocketDataProvider ssl_1(ASYNC, OK);
1068 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_1);
1069 SSLSocketDataProvider ssl_2(ASYNC, OK);
1070 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_2);
1071 SSLSocketDataProvider ssl_3(ASYNC, OK);
1072 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_3);
1073
1074 std::unique_ptr<HttpNetworkSession> session(
1075 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1076 ClientSocketPool* ssl_pool = session->GetSocketPool(
1077 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct());
1078
1079 EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 0);
1080
1081 HttpRequestInfo request_info;
1082 request_info.method = "GET";
1083 request_info.url = GURL("https://www.google.com");
1084 request_info.load_flags = 0;
1085 request_info.privacy_mode = PRIVACY_MODE_DISABLED;
1086 request_info.traffic_annotation =
1087 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1088
1089 StreamRequestWaiter waiter;
1090
1091 std::unique_ptr<HttpStreamRequest> request1(
1092 session->http_stream_factory()->RequestStream(
1093 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1094 /* enable_ip_based_pooling = */ true,
1095 /* enable_alternative_services = */ true, NetLogWithSource()));
1096 waiter.WaitForStream();
1097
1098 EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 1);
1099
1100 std::unique_ptr<HttpStreamRequest> request2(
1101 session->http_stream_factory()->RequestStream(
1102 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1103 /* enable_ip_based_pooling = */ true,
1104 /* enable_alternative_services = */ true, NetLogWithSource()));
1105 waiter.WaitForStream();
1106
1107 EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 1);
1108
1109 request_info.privacy_mode = PRIVACY_MODE_ENABLED;
1110 std::unique_ptr<HttpStreamRequest> request3(
1111 session->http_stream_factory()->RequestStream(
1112 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1113 /* enable_ip_based_pooling = */ true,
1114 /* enable_alternative_services = */ true, NetLogWithSource()));
1115 waiter.WaitForStream();
1116
1117 EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 2);
1118 }
1119
TEST_F(HttpStreamFactoryTest,DisableSecureDnsUsesDifferentSocketPoolGroup)1120 TEST_F(HttpStreamFactoryTest, DisableSecureDnsUsesDifferentSocketPoolGroup) {
1121 SpdySessionDependencies session_deps(
1122 ConfiguredProxyResolutionService::CreateDirect());
1123
1124 StaticSocketDataProvider socket_data_1;
1125 socket_data_1.set_connect_data(MockConnect(ASYNC, OK));
1126 session_deps.socket_factory->AddSocketDataProvider(&socket_data_1);
1127 StaticSocketDataProvider socket_data_2;
1128 socket_data_2.set_connect_data(MockConnect(ASYNC, OK));
1129 session_deps.socket_factory->AddSocketDataProvider(&socket_data_2);
1130 StaticSocketDataProvider socket_data_3;
1131 socket_data_3.set_connect_data(MockConnect(ASYNC, OK));
1132 session_deps.socket_factory->AddSocketDataProvider(&socket_data_3);
1133
1134 SSLSocketDataProvider ssl_1(ASYNC, OK);
1135 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_1);
1136 SSLSocketDataProvider ssl_2(ASYNC, OK);
1137 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_2);
1138 SSLSocketDataProvider ssl_3(ASYNC, OK);
1139 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_3);
1140
1141 std::unique_ptr<HttpNetworkSession> session(
1142 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1143 ClientSocketPool* ssl_pool = session->GetSocketPool(
1144 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct());
1145
1146 EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 0);
1147
1148 HttpRequestInfo request_info;
1149 request_info.method = "GET";
1150 request_info.url = GURL("https://www.google.com");
1151 request_info.load_flags = 0;
1152 request_info.privacy_mode = PRIVACY_MODE_DISABLED;
1153 request_info.traffic_annotation =
1154 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1155 request_info.secure_dns_policy = SecureDnsPolicy::kAllow;
1156
1157 StreamRequestWaiter waiter;
1158
1159 std::unique_ptr<HttpStreamRequest> request1(
1160 session->http_stream_factory()->RequestStream(
1161 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1162 /* enable_ip_based_pooling = */ true,
1163 /* enable_alternative_services = */ true, NetLogWithSource()));
1164 waiter.WaitForStream();
1165
1166 EXPECT_EQ(SecureDnsPolicy::kAllow,
1167 session_deps.host_resolver->last_secure_dns_policy());
1168 EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 1);
1169
1170 std::unique_ptr<HttpStreamRequest> request2(
1171 session->http_stream_factory()->RequestStream(
1172 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1173 /* enable_ip_based_pooling = */ true,
1174 /* enable_alternative_services = */ true, NetLogWithSource()));
1175 waiter.WaitForStream();
1176
1177 EXPECT_EQ(SecureDnsPolicy::kAllow,
1178 session_deps.host_resolver->last_secure_dns_policy());
1179 EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 1);
1180
1181 request_info.secure_dns_policy = SecureDnsPolicy::kDisable;
1182 std::unique_ptr<HttpStreamRequest> request3(
1183 session->http_stream_factory()->RequestStream(
1184 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1185 /* enable_ip_based_pooling = */ true,
1186 /* enable_alternative_services = */ true, NetLogWithSource()));
1187 waiter.WaitForStream();
1188
1189 EXPECT_EQ(SecureDnsPolicy::kDisable,
1190 session_deps.host_resolver->last_secure_dns_policy());
1191 EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 2);
1192 }
1193
TEST_F(HttpStreamFactoryTest,GetLoadState)1194 TEST_F(HttpStreamFactoryTest, GetLoadState) {
1195 SpdySessionDependencies session_deps(
1196 ConfiguredProxyResolutionService::CreateDirect());
1197
1198 StaticSocketDataProvider socket_data;
1199 socket_data.set_connect_data(MockConnect(ASYNC, OK));
1200 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
1201
1202 std::unique_ptr<HttpNetworkSession> session(
1203 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1204
1205 HttpRequestInfo request_info;
1206 request_info.method = "GET";
1207 request_info.url = GURL("http://www.google.com");
1208 request_info.traffic_annotation =
1209 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1210
1211 StreamRequestWaiter waiter;
1212 std::unique_ptr<HttpStreamRequest> request(
1213 session->http_stream_factory()->RequestStream(
1214 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1215 /* enable_ip_based_pooling = */ true,
1216 /* enable_alternative_services = */ true, NetLogWithSource()));
1217
1218 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, request->GetLoadState());
1219
1220 waiter.WaitForStream();
1221 }
1222
TEST_F(HttpStreamFactoryTest,RequestHttpStream)1223 TEST_F(HttpStreamFactoryTest, RequestHttpStream) {
1224 SpdySessionDependencies session_deps(
1225 ConfiguredProxyResolutionService::CreateDirect());
1226
1227 StaticSocketDataProvider socket_data;
1228 socket_data.set_connect_data(MockConnect(ASYNC, OK));
1229 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
1230
1231 std::unique_ptr<HttpNetworkSession> session(
1232 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1233
1234 // Now request a stream. It should succeed using the second proxy in the
1235 // list.
1236 HttpRequestInfo request_info;
1237 request_info.method = "GET";
1238 request_info.url = GURL("http://www.google.com");
1239 request_info.load_flags = 0;
1240 request_info.traffic_annotation =
1241 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1242
1243 StreamRequestWaiter waiter;
1244 std::unique_ptr<HttpStreamRequest> request(
1245 session->http_stream_factory()->RequestStream(
1246 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1247 /* enable_ip_based_pooling = */ true,
1248 /* enable_alternative_services = */ true, NetLogWithSource()));
1249 waiter.WaitForStream();
1250 EXPECT_TRUE(waiter.stream_done());
1251 ASSERT_TRUE(nullptr != waiter.stream());
1252 EXPECT_TRUE(nullptr == waiter.websocket_stream());
1253
1254 EXPECT_EQ(0, GetSpdySessionCount(session.get()));
1255 EXPECT_EQ(1,
1256 GetSocketPoolGroupCount(session->GetSocketPool(
1257 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
1258 EXPECT_TRUE(waiter.used_proxy_info().is_direct());
1259 }
1260
1261 // Test the race of SetPriority versus stream completion where SetPriority may
1262 // be called on an HttpStreamFactory::Job after the stream has been created by
1263 // the job.
TEST_F(HttpStreamFactoryTest,ReprioritizeAfterStreamReceived)1264 TEST_F(HttpStreamFactoryTest, ReprioritizeAfterStreamReceived) {
1265 SpdySessionDependencies session_deps(
1266 ConfiguredProxyResolutionService::CreateDirect());
1267 session_deps.host_resolver->set_synchronous_mode(true);
1268
1269 MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
1270 StaticSocketDataProvider socket_data(base::make_span(&mock_read, 1u),
1271 base::span<MockWrite>());
1272 socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1273 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
1274
1275 SSLSocketDataProvider ssl_socket_data(SYNCHRONOUS, OK);
1276 ssl_socket_data.next_proto = kProtoHTTP2;
1277 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
1278
1279 std::unique_ptr<HttpNetworkSession> session(
1280 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1281
1282 // Now request a stream.
1283 HttpRequestInfo request_info;
1284 request_info.method = "GET";
1285 request_info.url = GURL("https://www.google.com");
1286 request_info.load_flags = 0;
1287 request_info.traffic_annotation =
1288 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1289
1290 StreamRequestWaiter waiter;
1291 EXPECT_EQ(0, GetSpdySessionCount(session.get()));
1292 std::unique_ptr<HttpStreamRequest> request(
1293 session->http_stream_factory()->RequestStream(
1294 request_info, LOWEST, /* allowed_bad_certs = */ {}, &waiter,
1295 /* enable_ip_based_pooling = */ true,
1296 /* enable_alternative_services = */ true, NetLogWithSource()));
1297 EXPECT_FALSE(waiter.stream_done());
1298
1299 // Confirm a stream has been created by asserting that a new session
1300 // has been created. (The stream is only created at the SPDY level on
1301 // first write, which happens after the request has returned a stream).
1302 ASSERT_EQ(1, GetSpdySessionCount(session.get()));
1303
1304 // Test to confirm that a SetPriority received after the stream is created
1305 // but before the request returns it does not crash.
1306 request->SetPriority(HIGHEST);
1307
1308 waiter.WaitForStream();
1309 EXPECT_TRUE(waiter.stream_done());
1310 ASSERT_TRUE(waiter.stream());
1311 EXPECT_FALSE(waiter.websocket_stream());
1312 }
1313
TEST_F(HttpStreamFactoryTest,RequestHttpStreamOverSSL)1314 TEST_F(HttpStreamFactoryTest, RequestHttpStreamOverSSL) {
1315 SpdySessionDependencies session_deps(
1316 ConfiguredProxyResolutionService::CreateDirect());
1317
1318 MockRead mock_read(ASYNC, OK);
1319 StaticSocketDataProvider socket_data(base::make_span(&mock_read, 1u),
1320 base::span<MockWrite>());
1321 socket_data.set_connect_data(MockConnect(ASYNC, OK));
1322 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
1323
1324 SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
1325 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
1326
1327 std::unique_ptr<HttpNetworkSession> session(
1328 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1329
1330 // Now request a stream.
1331 HttpRequestInfo request_info;
1332 request_info.method = "GET";
1333 request_info.url = GURL("https://www.google.com");
1334 request_info.load_flags = 0;
1335 request_info.traffic_annotation =
1336 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1337
1338 StreamRequestWaiter waiter;
1339 std::unique_ptr<HttpStreamRequest> request(
1340 session->http_stream_factory()->RequestStream(
1341 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1342 /* enable_ip_based_pooling = */ true,
1343 /* enable_alternative_services = */ true, NetLogWithSource()));
1344 waiter.WaitForStream();
1345 EXPECT_TRUE(waiter.stream_done());
1346 ASSERT_TRUE(nullptr != waiter.stream());
1347 EXPECT_TRUE(nullptr == waiter.websocket_stream());
1348
1349 EXPECT_EQ(0, GetSpdySessionCount(session.get()));
1350 EXPECT_EQ(1,
1351 GetSocketPoolGroupCount(session->GetSocketPool(
1352 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
1353 EXPECT_TRUE(waiter.used_proxy_info().is_direct());
1354 }
1355
TEST_F(HttpStreamFactoryTest,RequestHttpStreamOverProxy)1356 TEST_F(HttpStreamFactoryTest, RequestHttpStreamOverProxy) {
1357 SpdySessionDependencies session_deps(
1358 ConfiguredProxyResolutionService::CreateFixedForTest(
1359 "myproxy:8888", TRAFFIC_ANNOTATION_FOR_TESTS));
1360
1361 StaticSocketDataProvider socket_data;
1362 socket_data.set_connect_data(MockConnect(ASYNC, OK));
1363 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
1364
1365 std::unique_ptr<HttpNetworkSession> session(
1366 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1367
1368 // Now request a stream. It should succeed using the second proxy in the
1369 // list.
1370 HttpRequestInfo request_info;
1371 request_info.method = "GET";
1372 request_info.url = GURL("http://www.google.com");
1373 request_info.load_flags = 0;
1374 request_info.traffic_annotation =
1375 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1376
1377 StreamRequestWaiter waiter;
1378 std::unique_ptr<HttpStreamRequest> request(
1379 session->http_stream_factory()->RequestStream(
1380 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1381 /* enable_ip_based_pooling = */ true,
1382 /* enable_alternative_services = */ true, NetLogWithSource()));
1383 waiter.WaitForStream();
1384 EXPECT_TRUE(waiter.stream_done());
1385 ASSERT_TRUE(nullptr != waiter.stream());
1386 EXPECT_TRUE(nullptr == waiter.websocket_stream());
1387
1388 EXPECT_EQ(0, GetSpdySessionCount(session.get()));
1389 EXPECT_EQ(0,
1390 GetSocketPoolGroupCount(session->GetSocketPool(
1391 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
1392 EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSocketPool(
1393 HttpNetworkSession::NORMAL_SOCKET_POOL,
1394 ProxyChain(ProxyServer::SCHEME_HTTP,
1395 HostPortPair("myproxy", 8888)))));
1396 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPool(
1397 HttpNetworkSession::NORMAL_SOCKET_POOL,
1398 ProxyChain(ProxyServer::SCHEME_HTTPS,
1399 HostPortPair("myproxy", 8888)))));
1400 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPool(
1401 HttpNetworkSession::WEBSOCKET_SOCKET_POOL,
1402 ProxyChain(ProxyServer::SCHEME_HTTP,
1403 HostPortPair("myproxy", 8888)))));
1404 EXPECT_FALSE(waiter.used_proxy_info().is_direct());
1405 }
1406
TEST_F(HttpStreamFactoryTest,RequestWebSocketBasicHandshakeStream)1407 TEST_F(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStream) {
1408 SpdySessionDependencies session_deps(
1409 ConfiguredProxyResolutionService::CreateDirect());
1410
1411 StaticSocketDataProvider socket_data;
1412 socket_data.set_connect_data(MockConnect(ASYNC, OK));
1413 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
1414
1415 std::unique_ptr<HttpNetworkSession> session(
1416 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1417
1418 // Now request a stream.
1419 HttpRequestInfo request_info;
1420 request_info.method = "GET";
1421 request_info.url = GURL("ws://www.google.com");
1422 request_info.load_flags = 0;
1423 request_info.traffic_annotation =
1424 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1425
1426 StreamRequestWaiter waiter;
1427 WebSocketStreamCreateHelper create_helper;
1428 std::unique_ptr<HttpStreamRequest> request(
1429 session->http_stream_factory()->RequestWebSocketHandshakeStream(
1430 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1431 &create_helper, /* enable_ip_based_pooling = */ true,
1432 /* enable_alternative_services = */ true, NetLogWithSource()));
1433 waiter.WaitForStream();
1434 EXPECT_TRUE(waiter.stream_done());
1435 EXPECT_TRUE(nullptr == waiter.stream());
1436 ASSERT_TRUE(nullptr != waiter.websocket_stream());
1437 EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic,
1438 waiter.websocket_stream()->type());
1439 EXPECT_EQ(0,
1440 GetSocketPoolGroupCount(session->GetSocketPool(
1441 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
1442 EXPECT_TRUE(waiter.used_proxy_info().is_direct());
1443 }
1444
TEST_F(HttpStreamFactoryTest,RequestWebSocketBasicHandshakeStreamOverSSL)1445 TEST_F(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverSSL) {
1446 SpdySessionDependencies session_deps(
1447 ConfiguredProxyResolutionService::CreateDirect());
1448
1449 MockRead mock_read(ASYNC, OK);
1450 StaticSocketDataProvider socket_data(base::make_span(&mock_read, 1u),
1451 base::span<MockWrite>());
1452 socket_data.set_connect_data(MockConnect(ASYNC, OK));
1453 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
1454
1455 SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
1456 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
1457
1458 std::unique_ptr<HttpNetworkSession> session(
1459 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1460
1461 // Now request a stream.
1462 HttpRequestInfo request_info;
1463 request_info.method = "GET";
1464 request_info.url = GURL("wss://www.google.com");
1465 request_info.load_flags = 0;
1466 request_info.traffic_annotation =
1467 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1468
1469 StreamRequestWaiter waiter;
1470 WebSocketStreamCreateHelper create_helper;
1471 std::unique_ptr<HttpStreamRequest> request(
1472 session->http_stream_factory()->RequestWebSocketHandshakeStream(
1473 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1474 &create_helper, /* enable_ip_based_pooling = */ true,
1475 /* enable_alternative_services = */ true, NetLogWithSource()));
1476 waiter.WaitForStream();
1477 EXPECT_TRUE(waiter.stream_done());
1478 EXPECT_TRUE(nullptr == waiter.stream());
1479 ASSERT_TRUE(nullptr != waiter.websocket_stream());
1480 EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic,
1481 waiter.websocket_stream()->type());
1482 EXPECT_EQ(0,
1483 GetSocketPoolGroupCount(session->GetSocketPool(
1484 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
1485 EXPECT_TRUE(waiter.used_proxy_info().is_direct());
1486 }
1487
TEST_F(HttpStreamFactoryTest,RequestWebSocketBasicHandshakeStreamOverProxy)1488 TEST_F(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverProxy) {
1489 SpdySessionDependencies session_deps(
1490 ConfiguredProxyResolutionService::CreateFixedForTest(
1491 "myproxy:8888", TRAFFIC_ANNOTATION_FOR_TESTS));
1492
1493 MockRead reads[] = {
1494 MockRead(SYNCHRONOUS, "HTTP/1.0 200 Connection established\r\n\r\n")};
1495 StaticSocketDataProvider socket_data(reads, base::span<MockWrite>());
1496 socket_data.set_connect_data(MockConnect(ASYNC, OK));
1497 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
1498
1499 std::unique_ptr<HttpNetworkSession> session(
1500 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1501
1502 // Now request a stream.
1503 HttpRequestInfo request_info;
1504 request_info.method = "GET";
1505 request_info.url = GURL("ws://www.google.com");
1506 request_info.load_flags = 0;
1507 request_info.traffic_annotation =
1508 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1509
1510 StreamRequestWaiter waiter;
1511 WebSocketStreamCreateHelper create_helper;
1512 std::unique_ptr<HttpStreamRequest> request(
1513 session->http_stream_factory()->RequestWebSocketHandshakeStream(
1514 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1515 &create_helper, /* enable_ip_based_pooling = */ true,
1516 /* enable_alternative_services = */ true, NetLogWithSource()));
1517 waiter.WaitForStream();
1518 EXPECT_TRUE(waiter.stream_done());
1519 EXPECT_TRUE(nullptr == waiter.stream());
1520 ASSERT_TRUE(nullptr != waiter.websocket_stream());
1521 EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic,
1522 waiter.websocket_stream()->type());
1523 EXPECT_EQ(
1524 0, GetSocketPoolGroupCount(session->GetSocketPool(
1525 HttpNetworkSession::WEBSOCKET_SOCKET_POOL, ProxyChain::Direct())));
1526 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPool(
1527 HttpNetworkSession::NORMAL_SOCKET_POOL,
1528 ProxyChain(ProxyServer::SCHEME_HTTP,
1529 HostPortPair("myproxy", 8888)))));
1530 EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSocketPool(
1531 HttpNetworkSession::WEBSOCKET_SOCKET_POOL,
1532 ProxyChain(ProxyServer::SCHEME_HTTP,
1533 HostPortPair("myproxy", 8888)))));
1534 EXPECT_FALSE(waiter.used_proxy_info().is_direct());
1535 }
1536
TEST_F(HttpStreamFactoryTest,RequestSpdyHttpStreamHttpsURL)1537 TEST_F(HttpStreamFactoryTest, RequestSpdyHttpStreamHttpsURL) {
1538 SpdySessionDependencies session_deps(
1539 ConfiguredProxyResolutionService::CreateDirect());
1540
1541 MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
1542 SequencedSocketData socket_data(base::make_span(&mock_read, 1u),
1543 base::span<MockWrite>());
1544 socket_data.set_connect_data(MockConnect(ASYNC, OK));
1545 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
1546
1547 SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
1548 ssl_socket_data.next_proto = kProtoHTTP2;
1549 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
1550
1551 HostPortPair host_port_pair("www.google.com", 443);
1552 std::unique_ptr<HttpNetworkSession> session(
1553 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1554
1555 // Now request a stream.
1556 HttpRequestInfo request_info;
1557 request_info.method = "GET";
1558 request_info.url = GURL("https://www.google.com");
1559 request_info.load_flags = 0;
1560 request_info.traffic_annotation =
1561 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1562
1563 StreamRequestWaiter waiter;
1564 std::unique_ptr<HttpStreamRequest> request(
1565 session->http_stream_factory()->RequestStream(
1566 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1567 /* enable_ip_based_pooling = */ true,
1568 /* enable_alternative_services = */ true, NetLogWithSource()));
1569 waiter.WaitForStream();
1570 EXPECT_TRUE(waiter.stream_done());
1571 EXPECT_TRUE(nullptr == waiter.websocket_stream());
1572 ASSERT_TRUE(nullptr != waiter.stream());
1573
1574 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
1575 EXPECT_EQ(1,
1576 GetSocketPoolGroupCount(session->GetSocketPool(
1577 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
1578 EXPECT_TRUE(waiter.used_proxy_info().is_direct());
1579 }
1580
TEST_F(HttpStreamFactoryTest,RequestSpdyHttpStreamHttpURL)1581 TEST_F(HttpStreamFactoryTest, RequestSpdyHttpStreamHttpURL) {
1582 url::SchemeHostPort scheme_host_port("http", "myproxy.org", 443);
1583 auto session_deps = std::make_unique<SpdySessionDependencies>(
1584 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
1585 "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS));
1586 std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
1587 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
1588 "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
1589
1590 MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
1591 SequencedSocketData socket_data(base::make_span(&mock_read, 1u),
1592 base::span<MockWrite>());
1593 socket_data.set_connect_data(MockConnect(ASYNC, OK));
1594 session_deps->socket_factory->AddSocketDataProvider(&socket_data);
1595
1596 SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
1597 ssl_socket_data.next_proto = kProtoHTTP2;
1598 session_deps->socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
1599 session_deps->proxy_resolution_service = std::move(proxy_resolution_service);
1600
1601 std::unique_ptr<HttpNetworkSession> session(
1602 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
1603
1604 HttpServerProperties* http_server_properties =
1605 session->spdy_session_pool()->http_server_properties();
1606 EXPECT_FALSE(http_server_properties->GetSupportsSpdy(
1607 scheme_host_port, NetworkAnonymizationKey()));
1608
1609 // Now request a stream.
1610 HttpRequestInfo request_info;
1611 request_info.method = "GET";
1612 request_info.url = GURL("http://www.google.com");
1613 request_info.load_flags = 0;
1614 request_info.traffic_annotation =
1615 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1616
1617 StreamRequestWaiter waiter;
1618 std::unique_ptr<HttpStreamRequest> request(
1619 session->http_stream_factory()->RequestStream(
1620 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1621 /* enable_ip_based_pooling = */ true,
1622 /* enable_alternative_services = */ true, NetLogWithSource()));
1623 waiter.WaitForStream();
1624 EXPECT_TRUE(waiter.stream_done());
1625 EXPECT_TRUE(nullptr == waiter.websocket_stream());
1626 ASSERT_TRUE(nullptr != waiter.stream());
1627
1628 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
1629 EXPECT_EQ(0,
1630 GetSocketPoolGroupCount(session->GetSocketPool(
1631 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
1632 EXPECT_FALSE(waiter.used_proxy_info().is_direct());
1633 EXPECT_TRUE(http_server_properties->GetSupportsSpdy(
1634 scheme_host_port, NetworkAnonymizationKey()));
1635 }
1636
1637 // Same as above, but checks HttpServerProperties is updated using the correct
1638 // NetworkAnonymizationKey. When/if NetworkAnonymizationKey is enabled by
1639 // default, this should probably be merged into the above test.
TEST_F(HttpStreamFactoryTest,RequestSpdyHttpStreamHttpURLWithNetworkAnonymizationKey)1640 TEST_F(HttpStreamFactoryTest,
1641 RequestSpdyHttpStreamHttpURLWithNetworkAnonymizationKey) {
1642 const SchemefulSite kSite1(GURL("https://foo.test/"));
1643 const auto kNetworkAnonymizationKey1 =
1644 NetworkAnonymizationKey::CreateSameSite(kSite1);
1645 const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
1646 const SchemefulSite kSite2(GURL("https://bar.test/"));
1647 const auto kNetworkAnonymizationKey2 =
1648 NetworkAnonymizationKey::CreateSameSite(kSite2);
1649 const NetworkIsolationKey kNetworkIsolationKey2(kSite1, kSite1);
1650
1651 base::test::ScopedFeatureList feature_list;
1652 feature_list.InitAndEnableFeature(
1653 features::kPartitionHttpServerPropertiesByNetworkIsolationKey);
1654
1655 url::SchemeHostPort scheme_host_port("http", "myproxy.org", 443);
1656 auto session_deps = std::make_unique<SpdySessionDependencies>(
1657 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
1658 "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS));
1659 std::unique_ptr<ProxyResolutionService> proxy_resolution_service =
1660 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
1661 "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS);
1662
1663 MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
1664 SequencedSocketData socket_data(base::make_span(&mock_read, 1u),
1665 base::span<MockWrite>());
1666 socket_data.set_connect_data(MockConnect(ASYNC, OK));
1667 session_deps->socket_factory->AddSocketDataProvider(&socket_data);
1668
1669 SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
1670 ssl_socket_data.next_proto = kProtoHTTP2;
1671 session_deps->socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
1672 session_deps->proxy_resolution_service = std::move(proxy_resolution_service);
1673
1674 std::unique_ptr<HttpNetworkSession> session(
1675 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
1676
1677 HttpServerProperties* http_server_properties =
1678 session->spdy_session_pool()->http_server_properties();
1679 EXPECT_FALSE(http_server_properties->GetSupportsSpdy(
1680 scheme_host_port, kNetworkAnonymizationKey1));
1681
1682 // Now request a stream.
1683 HttpRequestInfo request_info;
1684 request_info.method = "GET";
1685 request_info.url = GURL("http://www.google.com");
1686 request_info.load_flags = 0;
1687 request_info.network_isolation_key = kNetworkIsolationKey1;
1688 request_info.network_anonymization_key = kNetworkAnonymizationKey1;
1689 request_info.traffic_annotation =
1690 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1691
1692 StreamRequestWaiter waiter;
1693 std::unique_ptr<HttpStreamRequest> request(
1694 session->http_stream_factory()->RequestStream(
1695 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1696 /* enable_ip_based_pooling = */ true,
1697 /* enable_alternative_services = */ true, NetLogWithSource()));
1698 waiter.WaitForStream();
1699 EXPECT_TRUE(waiter.stream_done());
1700 EXPECT_TRUE(nullptr == waiter.websocket_stream());
1701 ASSERT_TRUE(nullptr != waiter.stream());
1702
1703 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
1704 EXPECT_EQ(0,
1705 GetSocketPoolGroupCount(session->GetSocketPool(
1706 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
1707 EXPECT_FALSE(waiter.used_proxy_info().is_direct());
1708 EXPECT_TRUE(http_server_properties->GetSupportsSpdy(
1709 scheme_host_port, kNetworkAnonymizationKey1));
1710 // Other NetworkAnonymizationKeys should not be recorded as supporting SPDY.
1711 EXPECT_FALSE(http_server_properties->GetSupportsSpdy(
1712 scheme_host_port, NetworkAnonymizationKey()));
1713 EXPECT_FALSE(http_server_properties->GetSupportsSpdy(
1714 scheme_host_port, kNetworkAnonymizationKey2));
1715 }
1716
1717 // Tests that when a new SpdySession is established, duplicated idle H2 sockets
1718 // to the same server are closed.
TEST_F(HttpStreamFactoryTest,NewSpdySessionCloseIdleH2Sockets)1719 TEST_F(HttpStreamFactoryTest, NewSpdySessionCloseIdleH2Sockets) {
1720 SpdySessionDependencies session_deps(
1721 ConfiguredProxyResolutionService::CreateDirect());
1722
1723 const int kNumIdleSockets = 4;
1724 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
1725 std::vector<std::unique_ptr<SequencedSocketData>> providers;
1726 SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
1727 ssl_socket_data.next_proto = kProtoHTTP2;
1728 for (int i = 0; i < kNumIdleSockets; i++) {
1729 auto provider =
1730 std::make_unique<SequencedSocketData>(reads, base::span<MockWrite>());
1731 provider->set_connect_data(MockConnect(ASYNC, OK));
1732 session_deps.socket_factory->AddSocketDataProvider(provider.get());
1733 providers.push_back(std::move(provider));
1734 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
1735 }
1736
1737 std::unique_ptr<HttpNetworkSession> session(
1738 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1739
1740 url::SchemeHostPort destination(url::kHttpsScheme, "www.google.com", 443);
1741
1742 // Create some HTTP/2 sockets.
1743 std::vector<std::unique_ptr<ClientSocketHandle>> handles;
1744 for (size_t i = 0; i < kNumIdleSockets; i++) {
1745 auto connection = std::make_unique<ClientSocketHandle>();
1746 TestCompletionCallback callback;
1747 scoped_refptr<ClientSocketPool::SocketParams> socket_params =
1748 base::MakeRefCounted<ClientSocketPool::SocketParams>(
1749 /*allowed_bad_certs=*/std::vector<SSLConfig::CertAndStatus>());
1750 ClientSocketPool::GroupId group_id(
1751 destination, PrivacyMode::PRIVACY_MODE_DISABLED,
1752 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
1753 /*disable_cert_network_fetches=*/false);
1754 int rv = connection->Init(
1755 group_id, socket_params, std::nullopt /* proxy_annotation_tag */,
1756 MEDIUM, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
1757 callback.callback(), ClientSocketPool::ProxyAuthCallback(),
1758 session->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
1759 ProxyChain::Direct()),
1760 NetLogWithSource());
1761 rv = callback.GetResult(rv);
1762 handles.push_back(std::move(connection));
1763 }
1764
1765 // Releases handles now, and these sockets should go into the socket pool.
1766 handles.clear();
1767 EXPECT_EQ(kNumIdleSockets,
1768 session
1769 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
1770 ProxyChain::Direct())
1771 ->IdleSocketCount());
1772
1773 // Request two streams at once and make sure they use the same connection.
1774 HttpRequestInfo request_info;
1775 request_info.method = "GET";
1776 request_info.url = GURL("https://www.google.com");
1777 request_info.load_flags = 0;
1778 request_info.traffic_annotation =
1779 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1780
1781 StreamRequestWaiter waiter1;
1782 StreamRequestWaiter waiter2;
1783 std::unique_ptr<HttpStreamRequest> request1(
1784 session->http_stream_factory()->RequestStream(
1785 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
1786 &waiter1, /* enable_ip_based_pooling = */ true,
1787 /* enable_alternative_services = */ true, NetLogWithSource()));
1788 std::unique_ptr<HttpStreamRequest> request2(
1789 session->http_stream_factory()->RequestStream(
1790 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
1791 &waiter2, /* enable_ip_based_pooling = */ true,
1792 /* enable_alternative_services = */ true, NetLogWithSource()));
1793 waiter1.WaitForStream();
1794 waiter2.WaitForStream();
1795 EXPECT_TRUE(waiter1.stream_done());
1796 EXPECT_TRUE(waiter2.stream_done());
1797 ASSERT_NE(nullptr, waiter1.stream());
1798 ASSERT_NE(nullptr, waiter2.stream());
1799 ASSERT_NE(waiter1.stream(), waiter2.stream());
1800
1801 // Establishing the SpdySession will close idle H2 sockets.
1802 EXPECT_EQ(0, session
1803 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
1804 ProxyChain::Direct())
1805 ->IdleSocketCount());
1806 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
1807 }
1808
1809 // Regression test for https://crbug.com/706974.
TEST_F(HttpStreamFactoryTest,TwoSpdyConnects)1810 TEST_F(HttpStreamFactoryTest, TwoSpdyConnects) {
1811 SpdySessionDependencies session_deps(
1812 ConfiguredProxyResolutionService::CreateDirect());
1813
1814 SSLSocketDataProvider ssl_socket_data0(ASYNC, OK);
1815 ssl_socket_data0.next_proto = kProtoHTTP2;
1816 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data0);
1817
1818 MockRead reads0[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
1819 SequencedSocketData data0(reads0, base::span<MockWrite>());
1820 data0.set_connect_data(MockConnect(ASYNC, OK));
1821 session_deps.socket_factory->AddSocketDataProvider(&data0);
1822
1823 SSLSocketDataProvider ssl_socket_data1(ASYNC, OK);
1824 ssl_socket_data1.next_proto = kProtoHTTP2;
1825 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data1);
1826
1827 SequencedSocketData data1;
1828 data1.set_connect_data(MockConnect(ASYNC, OK));
1829 session_deps.socket_factory->AddSocketDataProvider(&data1);
1830
1831 std::unique_ptr<HttpNetworkSession> session =
1832 SpdySessionDependencies::SpdyCreateSession(&session_deps);
1833 HttpRequestInfo request_info;
1834 request_info.method = "GET";
1835 request_info.url = GURL("https://www.google.com");
1836 request_info.load_flags = 0;
1837 request_info.traffic_annotation =
1838 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1839
1840 // Request two streams at once and make sure they use the same connection.
1841 StreamRequestWaiter waiter1;
1842 std::unique_ptr<HttpStreamRequest> request1 =
1843 session->http_stream_factory()->RequestStream(
1844 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
1845 &waiter1, /* enable_ip_based_pooling = */ true,
1846 /* enable_alternative_services = */ true, NetLogWithSource());
1847
1848 StreamRequestWaiter waiter2;
1849 std::unique_ptr<HttpStreamRequest> request2 =
1850 session->http_stream_factory()->RequestStream(
1851 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
1852 &waiter2, /* enable_ip_based_pooling = */ true,
1853 /* enable_alternative_services = */ true, NetLogWithSource());
1854
1855 waiter1.WaitForStream();
1856 waiter2.WaitForStream();
1857
1858 EXPECT_TRUE(waiter1.stream_done());
1859 EXPECT_TRUE(waiter2.stream_done());
1860 ASSERT_NE(nullptr, waiter1.stream());
1861 ASSERT_NE(nullptr, waiter2.stream());
1862 ASSERT_NE(waiter1.stream(), waiter2.stream());
1863
1864 // Establishing the SpdySession will close the extra H2 socket.
1865 EXPECT_EQ(0, session
1866 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
1867 ProxyChain::Direct())
1868 ->IdleSocketCount());
1869 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
1870 EXPECT_TRUE(data0.AllReadDataConsumed());
1871 EXPECT_TRUE(data1.AllReadDataConsumed());
1872 }
1873
TEST_F(HttpStreamFactoryTest,RequestBidirectionalStreamImpl)1874 TEST_F(HttpStreamFactoryTest, RequestBidirectionalStreamImpl) {
1875 SpdySessionDependencies session_deps(
1876 ConfiguredProxyResolutionService::CreateDirect());
1877
1878 MockRead mock_read(ASYNC, OK);
1879 SequencedSocketData socket_data(base::make_span(&mock_read, 1u),
1880 base::span<MockWrite>());
1881 socket_data.set_connect_data(MockConnect(ASYNC, OK));
1882 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
1883
1884 SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
1885 ssl_socket_data.next_proto = kProtoHTTP2;
1886 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
1887
1888 std::unique_ptr<HttpNetworkSession> session(
1889 SpdySessionDependencies::SpdyCreateSession(&session_deps));
1890
1891 // Now request a stream.
1892 HttpRequestInfo request_info;
1893 request_info.method = "GET";
1894 request_info.url = GURL("https://www.google.com");
1895 request_info.load_flags = 0;
1896 request_info.traffic_annotation =
1897 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1898
1899 StreamRequestWaiter waiter;
1900 std::unique_ptr<HttpStreamRequest> request(
1901 session->http_stream_factory()->RequestBidirectionalStreamImpl(
1902 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
1903 /* enable_ip_based_pooling = */ true,
1904 /* enable_alternative_services = */ true, NetLogWithSource()));
1905 waiter.WaitForStream();
1906 EXPECT_TRUE(waiter.stream_done());
1907 EXPECT_FALSE(waiter.websocket_stream());
1908 ASSERT_FALSE(waiter.stream());
1909 ASSERT_TRUE(waiter.bidirectional_stream_impl());
1910 EXPECT_EQ(1,
1911 GetSocketPoolGroupCount(session->GetSocketPool(
1912 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
1913 EXPECT_TRUE(waiter.used_proxy_info().is_direct());
1914 }
1915
1916 // Tests for creating an HTTP stream via QUIC.
1917 class HttpStreamFactoryQuicTest
1918 : public TestWithTaskEnvironment,
1919 public ::testing::WithParamInterface<quic::ParsedQuicVersion> {
1920 protected:
HttpStreamFactoryQuicTest()1921 HttpStreamFactoryQuicTest()
1922 : version_(GetParam()),
1923 quic_context_(std::make_unique<MockQuicContext>()),
1924 session_deps_(ConfiguredProxyResolutionService::CreateDirect()),
1925 clock_(quic_context_->clock()),
1926 random_generator_(quic_context_->random_generator()) {
1927 FLAGS_quic_enable_http3_grease_randomness = false;
1928 quic::QuicEnableVersion(version_);
1929 quic_context_->params()->supported_versions =
1930 quic::test::SupportedVersions(version_);
1931 quic_context_->params()->origins_to_force_quic_on.insert(
1932 HostPortPair::FromString("www.example.org:443"));
1933 quic_context_->AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
1934 session_deps_.enable_quic = true;
1935 session_deps_.quic_context = std::move(quic_context_);
1936
1937 // Load a certificate that is valid for *.example.org
1938 scoped_refptr<X509Certificate> test_cert(
1939 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
1940 EXPECT_TRUE(test_cert.get());
1941 verify_details_.cert_verify_result.verified_cert = test_cert;
1942 verify_details_.cert_verify_result.is_issued_by_known_root = true;
1943 auto mock_crypto_client_stream_factory =
1944 std::make_unique<MockCryptoClientStreamFactory>();
1945 mock_crypto_client_stream_factory->AddProofVerifyDetails(&verify_details_);
1946 mock_crypto_client_stream_factory->set_handshake_mode(
1947 MockCryptoClientStream::CONFIRM_HANDSHAKE);
1948 session_deps_.quic_crypto_client_stream_factory =
1949 std::move(mock_crypto_client_stream_factory);
1950
1951 session_deps_.http_user_agent_settings =
1952 std::make_unique<StaticHttpUserAgentSettings>("test-lang", "test-ua");
1953 }
1954
MakeSession()1955 HttpNetworkSession* MakeSession() {
1956 session_ = SpdySessionDependencies::SpdyCreateSessionWithSocketFactory(
1957 &session_deps_, &socket_factory_);
1958 session_->quic_session_pool()->set_is_quic_known_to_work_on_current_network(
1959 true);
1960 return session_.get();
1961 }
1962
TearDown()1963 void TearDown() override { session_.reset(); }
1964
ConstructInitialSettingsPacket(test::QuicTestPacketMaker & packet_maker,uint64_t packet_number)1965 std::unique_ptr<quic::QuicEncryptedPacket> ConstructInitialSettingsPacket(
1966 test::QuicTestPacketMaker& packet_maker,
1967 uint64_t packet_number) {
1968 return packet_maker.MakeInitialSettingsPacket(packet_number);
1969 }
1970
ConstructAckPacket(test::QuicTestPacketMaker & packet_maker,uint64_t packet_number,uint64_t packet_num_received,uint64_t smallest_received,uint64_t largest_received)1971 std::unique_ptr<quic::QuicEncryptedPacket> ConstructAckPacket(
1972 test::QuicTestPacketMaker& packet_maker,
1973 uint64_t packet_number,
1974 uint64_t packet_num_received,
1975 uint64_t smallest_received,
1976 uint64_t largest_received) {
1977 return packet_maker.MakeAckPacket(packet_number, packet_num_received,
1978 smallest_received, largest_received);
1979 }
1980
ConstructConnectUdpRequestPacket(test::QuicTestPacketMaker & packet_maker,uint64_t packet_number,quic::QuicStreamId stream_id,std::string authority,std::string path,bool fin)1981 std::unique_ptr<quic::QuicEncryptedPacket> ConstructConnectUdpRequestPacket(
1982 test::QuicTestPacketMaker& packet_maker,
1983 uint64_t packet_number,
1984 quic::QuicStreamId stream_id,
1985 std::string authority,
1986 std::string path,
1987 bool fin) {
1988 spdy::Http2HeaderBlock headers;
1989 headers[":scheme"] = "https";
1990 headers[":path"] = path;
1991 headers[":protocol"] = "connect-udp";
1992 headers[":method"] = "CONNECT";
1993 headers[":authority"] = authority;
1994 headers["user-agent"] = "test-ua";
1995 headers["capsule-protocol"] = "?1";
1996 spdy::SpdyPriority priority =
1997 ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
1998 size_t spdy_headers_frame_len;
1999 auto rv = packet_maker.MakeRequestHeadersPacket(
2000 packet_number, stream_id, fin, priority, std::move(headers),
2001 &spdy_headers_frame_len, /*should_include_priority_frame=*/false);
2002 return rv;
2003 }
2004
ConstructOkResponsePacket(test::QuicTestPacketMaker & packet_maker,uint64_t packet_number,quic::QuicStreamId stream_id,bool fin)2005 std::unique_ptr<quic::QuicEncryptedPacket> ConstructOkResponsePacket(
2006 test::QuicTestPacketMaker& packet_maker,
2007 uint64_t packet_number,
2008 quic::QuicStreamId stream_id,
2009 bool fin) {
2010 spdy::Http2HeaderBlock headers = packet_maker.GetResponseHeaders("200");
2011 size_t spdy_headers_frame_len;
2012 return packet_maker.MakeResponseHeadersPacket(packet_number, stream_id, fin,
2013 std::move(headers),
2014 &spdy_headers_frame_len);
2015 }
2016
2017 std::unique_ptr<quic::QuicEncryptedPacket>
ConstructAckAndClientH3DatagramPacket(test::QuicTestPacketMaker & packet_maker,uint64_t packet_number,uint64_t largest_received,uint64_t smallest_received,uint64_t quarter_stream_id,uint64_t context_id,std::unique_ptr<quic::QuicEncryptedPacket> packet)2018 ConstructAckAndClientH3DatagramPacket(
2019 test::QuicTestPacketMaker& packet_maker,
2020 uint64_t packet_number,
2021 uint64_t largest_received,
2022 uint64_t smallest_received,
2023 uint64_t quarter_stream_id,
2024 uint64_t context_id,
2025 std::unique_ptr<quic::QuicEncryptedPacket> packet) {
2026 std::string datagram;
2027 // Allow enough space for payload and two varint-62's.
2028 datagram.resize(packet->length() + 2 * 8);
2029 quiche::QuicheDataWriter writer(datagram.capacity(), datagram.data());
2030 CHECK(writer.WriteVarInt62(quarter_stream_id));
2031 CHECK(writer.WriteVarInt62(context_id));
2032 CHECK(writer.WriteBytes(packet->data(), packet->length()));
2033 datagram.resize(writer.length());
2034 return packet_maker.MakeAckAndDatagramPacket(
2035 packet_number, largest_received, smallest_received, datagram);
2036 }
2037
ConstructClientH3DatagramPacket(test::QuicTestPacketMaker & packet_maker,uint64_t packet_number,uint64_t quarter_stream_id,uint64_t context_id,std::vector<std::unique_ptr<quic::QuicEncryptedPacket>> packets)2038 std::unique_ptr<quic::QuicEncryptedPacket> ConstructClientH3DatagramPacket(
2039 test::QuicTestPacketMaker& packet_maker,
2040 uint64_t packet_number,
2041 uint64_t quarter_stream_id,
2042 uint64_t context_id,
2043 std::vector<std::unique_ptr<quic::QuicEncryptedPacket>> packets) {
2044 std::vector<std::string> datagrams;
2045 for (auto& packet : packets) {
2046 std::string data;
2047 // Allow enough space for payload and two varint-62's.
2048 data.resize(packet->length() + 2 * 8);
2049 quiche::QuicheDataWriter writer(data.capacity(), data.data());
2050 CHECK(writer.WriteVarInt62(quarter_stream_id));
2051 CHECK(writer.WriteVarInt62(context_id));
2052 CHECK(writer.WriteBytes(packet->data(), packet->length()));
2053 data.resize(writer.length());
2054 datagrams.push_back(std::move(data));
2055 }
2056 return packet_maker.MakeDatagramPacket(packet_number, datagrams);
2057 }
2058
2059 // Make a `QuicTestPacketMaker` for the current test with the given
2060 // characteristics.
MakePacketMaker(const std::string & host,quic::Perspective perspective,bool client_priority_uses_incremental=false,bool use_priority_header=false)2061 test::QuicTestPacketMaker MakePacketMaker(
2062 const std::string& host,
2063 quic::Perspective perspective,
2064 bool client_priority_uses_incremental = false,
2065 bool use_priority_header = false) {
2066 return test::QuicTestPacketMaker(
2067 version_, quic::QuicUtils::CreateRandomConnectionId(random_generator_),
2068 clock_, host, perspective, client_priority_uses_incremental,
2069 use_priority_header);
2070 }
2071
socket_factory()2072 MockTaggingClientSocketFactory* socket_factory() { return &socket_factory_; }
2073
GetNthClientInitiatedBidirectionalStreamId(int n)2074 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
2075 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
2076 version_.transport_version, n);
2077 }
2078
session_deps()2079 SpdySessionDependencies& session_deps() { return session_deps_; }
2080
version() const2081 quic::ParsedQuicVersion version() const { return version_; }
2082
2083 private:
2084 quic::test::QuicFlagSaver saver_;
2085 const quic::ParsedQuicVersion version_;
2086 std::unique_ptr<MockQuicContext> quic_context_;
2087 SpdySessionDependencies session_deps_;
2088 raw_ptr<const quic::QuicClock> clock_;
2089 raw_ptr<quic::QuicRandom> random_generator_;
2090 MockTaggingClientSocketFactory socket_factory_;
2091 std::unique_ptr<HttpNetworkSession> session_;
2092 ProofVerifyDetailsChromium verify_details_;
2093 };
2094
2095 INSTANTIATE_TEST_SUITE_P(All,
2096 HttpStreamFactoryQuicTest,
2097 ::testing::ValuesIn(AllSupportedQuicVersions()),
2098 ::testing::PrintToStringParamName());
2099
2100 // Check that requesting an HTTP stream over a QUIC proxy sends the correct
2101 // set of QUIC packets.
TEST_P(HttpStreamFactoryQuicTest,RequestHttpStreamOverQuicProxy)2102 TEST_P(HttpStreamFactoryQuicTest, RequestHttpStreamOverQuicProxy) {
2103 static constexpr uint64_t kConnectUdpContextId = 0;
2104 GURL kRequestUrl("https://www.example.org");
2105 session_deps().proxy_resolution_service =
2106 ConfiguredProxyResolutionService::CreateFixedFromProxyChainsForTest(
2107 {ProxyChain::ForIpProtection({ProxyServer::FromSchemeHostAndPort(
2108 ProxyServer::SCHEME_QUIC, "qproxy.example.org", 8888)})},
2109 TRAFFIC_ANNOTATION_FOR_TESTS);
2110
2111 MockQuicData proxy_quic_data(version());
2112 quic::QuicStreamId stream_id = GetNthClientInitiatedBidirectionalStreamId(0);
2113 int to_proxy_packet_num = 1;
2114 auto to_proxy =
2115 MakePacketMaker("qproxy.example.org", quic::Perspective::IS_CLIENT,
2116 /*client_priority_uses_incremental=*/true,
2117 /*use_priority_header=*/false);
2118 int from_proxy_packet_num = 1;
2119 auto from_proxy =
2120 MakePacketMaker("qproxy.example.org", quic::Perspective::IS_SERVER,
2121 /*client_priority_uses_incremental=*/false,
2122 /*use_priority_header=*/false);
2123 int to_endpoint_packet_num = 1;
2124 auto to_endpoint =
2125 MakePacketMaker("www.example.org", quic::Perspective::IS_CLIENT,
2126 /*client_priority_uses_incremental=*/true,
2127 /*use_priority_header=*/true);
2128
2129 // The browser sends initial settings to the proxy.
2130 proxy_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(
2131 to_proxy, to_proxy_packet_num++));
2132
2133 // The browser sends CONNECT-UDP request to proxy.
2134 proxy_quic_data.AddWrite(
2135 SYNCHRONOUS,
2136 ConstructConnectUdpRequestPacket(
2137 to_proxy, to_proxy_packet_num++, stream_id, "qproxy.example.org:8888",
2138 "/.well-known/masque/udp/www.example.org/443/", false));
2139
2140 // Proxy sends initial settings.
2141 proxy_quic_data.AddRead(ASYNC, ConstructInitialSettingsPacket(
2142 from_proxy, from_proxy_packet_num++));
2143
2144 // Proxy responds to the CONNECT.
2145 proxy_quic_data.AddRead(
2146 ASYNC, ConstructOkResponsePacket(from_proxy, from_proxy_packet_num++,
2147 stream_id, true));
2148 proxy_quic_data.AddReadPauseForever();
2149
2150 // The browser ACKs the OK response packet.
2151 proxy_quic_data.AddWrite(
2152 ASYNC, ConstructAckPacket(to_proxy, to_proxy_packet_num++, 1, 2, 1));
2153
2154 // The browser sends initial settings to the endpoint, via proxy.
2155 std::vector<std::unique_ptr<quic::QuicEncryptedPacket>> datagrams;
2156 datagrams.push_back(
2157 ConstructInitialSettingsPacket(to_endpoint, to_endpoint_packet_num++));
2158 proxy_quic_data.AddWrite(
2159 ASYNC, ConstructClientH3DatagramPacket(to_proxy, to_proxy_packet_num++,
2160 stream_id, kConnectUdpContextId,
2161 std::move(datagrams)));
2162
2163 proxy_quic_data.AddSocketDataToFactory(socket_factory());
2164
2165 HttpNetworkSession* session = MakeSession();
2166
2167 HttpRequestInfo request_info;
2168 request_info.method = "GET";
2169 request_info.url = kRequestUrl;
2170 request_info.load_flags = 0;
2171 request_info.traffic_annotation =
2172 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2173
2174 StreamRequestWaiter waiter;
2175 std::unique_ptr<HttpStreamRequest> request(
2176 session->http_stream_factory()->RequestStream(
2177 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
2178 /* enable_ip_based_pooling = */ true,
2179 /* enable_alternative_services = */ true, NetLogWithSource()));
2180
2181 waiter.WaitForStream();
2182 EXPECT_TRUE(waiter.stream_done());
2183 EXPECT_FALSE(waiter.websocket_stream());
2184 EXPECT_TRUE(waiter.stream());
2185 EXPECT_FALSE(waiter.used_proxy_info().is_direct());
2186
2187 RunUntilIdle();
2188
2189 proxy_quic_data.ExpectAllReadDataConsumed();
2190 proxy_quic_data.ExpectAllWriteDataConsumed();
2191 }
2192
2193 // Check that requesting an HTTP stream over a two QUIC proxies sends the
2194 // correct set of QUIC packets.
TEST_P(HttpStreamFactoryQuicTest,RequestHttpStreamOverTwoQuicProxies)2195 TEST_P(HttpStreamFactoryQuicTest, RequestHttpStreamOverTwoQuicProxies) {
2196 static constexpr uint64_t kConnectUdpContextId = 0;
2197 GURL kRequestUrl("https://www.example.org");
2198 session_deps().proxy_resolution_service =
2199 ConfiguredProxyResolutionService::CreateFixedFromProxyChainsForTest(
2200 {
2201 ProxyChain::ForIpProtection(
2202 {ProxyServer::FromSchemeHostAndPort(
2203 ProxyServer::SCHEME_QUIC, "qproxy1.example.org", 8888),
2204 ProxyServer::FromSchemeHostAndPort(
2205 ProxyServer::SCHEME_QUIC, "qproxy2.example.org", 8888)}),
2206 },
2207 TRAFFIC_ANNOTATION_FOR_TESTS);
2208
2209 MockQuicData proxy_quic_data(version());
2210 quic::QuicStreamId stream_id_0 =
2211 GetNthClientInitiatedBidirectionalStreamId(0);
2212 int to_proxy1_packet_num = 1;
2213 auto to_proxy1 =
2214 MakePacketMaker("qproxy1.example.org", quic::Perspective::IS_CLIENT,
2215 /*client_priority_uses_incremental=*/true,
2216 /*use_priority_header=*/false);
2217 int from_proxy1_packet_num = 1;
2218 auto from_proxy1 =
2219 MakePacketMaker("qproxy1.example.org", quic::Perspective::IS_SERVER,
2220 /*client_priority_uses_incremental=*/false,
2221 /*use_priority_header=*/false);
2222 int to_proxy2_packet_num = 1;
2223 auto to_proxy2 =
2224 MakePacketMaker("qproxy2.example.org", quic::Perspective::IS_CLIENT,
2225 /*client_priority_uses_incremental=*/true,
2226 /*use_priority_header=*/false);
2227 int from_proxy2_packet_num = 1;
2228 auto from_proxy2 =
2229 MakePacketMaker("qproxy2.example.org", quic::Perspective::IS_SERVER,
2230 /*client_priority_uses_incremental=*/false,
2231 /*use_priority_header=*/false);
2232 int to_endpoint_packet_num = 1;
2233 auto to_endpoint =
2234 MakePacketMaker("www.example.org", quic::Perspective::IS_CLIENT,
2235 /*client_priority_uses_incremental=*/true,
2236 /*use_priority_header=*/true);
2237
2238 // The browser sends initial settings to proxy1.
2239 proxy_quic_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket(
2240 to_proxy1, to_proxy1_packet_num++));
2241
2242 // The browser sends CONNECT-UDP request to proxy1.
2243 proxy_quic_data.AddWrite(
2244 SYNCHRONOUS,
2245 ConstructConnectUdpRequestPacket(
2246 to_proxy1, to_proxy1_packet_num++, stream_id_0,
2247 "qproxy1.example.org:8888",
2248 "/.well-known/masque/udp/qproxy2.example.org/8888/", false));
2249
2250 // Proxy1 sends initial settings.
2251 proxy_quic_data.AddRead(ASYNC, ConstructInitialSettingsPacket(
2252 from_proxy1, from_proxy1_packet_num++));
2253
2254 // Proxy1 responds to the CONNECT.
2255 proxy_quic_data.AddRead(
2256 ASYNC, ConstructOkResponsePacket(from_proxy1, from_proxy1_packet_num++,
2257 stream_id_0, true));
2258
2259 // The browser ACKs the OK response packet.
2260 proxy_quic_data.AddWrite(
2261 ASYNC, ConstructAckPacket(to_proxy1, to_proxy1_packet_num++, 1, 2, 1));
2262
2263 // The browser sends initial settings and a CONNECT-UDP request to proxy2 via
2264 // proxy1.
2265 std::vector<std::unique_ptr<quic::QuicEncryptedPacket>> datagrams;
2266 datagrams.push_back(
2267 ConstructInitialSettingsPacket(to_proxy2, to_proxy2_packet_num++));
2268 datagrams.push_back(ConstructConnectUdpRequestPacket(
2269 to_proxy2, to_proxy2_packet_num++, stream_id_0,
2270 "qproxy2.example.org:8888",
2271 "/.well-known/masque/udp/www.example.org/443/", false));
2272 proxy_quic_data.AddWrite(
2273 ASYNC, ConstructClientH3DatagramPacket(to_proxy1, to_proxy1_packet_num++,
2274 stream_id_0, kConnectUdpContextId,
2275 std::move(datagrams)));
2276
2277 // Proxy2 sends initial settings and an OK response to the CONNECT request,
2278 // via proxy1.
2279 datagrams.clear();
2280 datagrams.push_back(
2281 ConstructInitialSettingsPacket(from_proxy2, from_proxy2_packet_num++));
2282 datagrams.push_back(ConstructOkResponsePacket(
2283 from_proxy2, from_proxy2_packet_num++, stream_id_0, true));
2284 proxy_quic_data.AddRead(
2285 ASYNC, ConstructClientH3DatagramPacket(
2286 from_proxy1, from_proxy1_packet_num++, stream_id_0,
2287 kConnectUdpContextId, std::move(datagrams)));
2288 proxy_quic_data.AddReadPauseForever();
2289
2290 // The browser ACK's the datagram from proxy1, and acks proxy2's OK response
2291 // packet via proxy1.
2292 proxy_quic_data.AddWrite(
2293 ASYNC,
2294 ConstructAckAndClientH3DatagramPacket(
2295 to_proxy1, to_proxy1_packet_num++, 3, 1, stream_id_0,
2296 kConnectUdpContextId,
2297 ConstructAckPacket(to_proxy2, to_proxy2_packet_num++, 1, 2, 1)));
2298
2299 // The browser sends initial settings to the endpoint, via proxy2, via proxy1.
2300 datagrams.clear();
2301 std::vector<std::unique_ptr<quic::QuicEncryptedPacket>> inner_datagrams;
2302 inner_datagrams.push_back(
2303 ConstructInitialSettingsPacket(to_endpoint, to_endpoint_packet_num++));
2304 datagrams.push_back(ConstructClientH3DatagramPacket(
2305 to_proxy2, to_proxy2_packet_num++, stream_id_0, kConnectUdpContextId,
2306 std::move(inner_datagrams)));
2307 proxy_quic_data.AddWrite(
2308 ASYNC, ConstructClientH3DatagramPacket(to_proxy1, to_proxy1_packet_num++,
2309 stream_id_0, kConnectUdpContextId,
2310 std::move(datagrams)));
2311
2312 proxy_quic_data.AddSocketDataToFactory(socket_factory());
2313
2314 HttpNetworkSession* session = MakeSession();
2315
2316 HttpRequestInfo request_info;
2317 request_info.method = "GET";
2318 request_info.url = kRequestUrl;
2319 request_info.load_flags = 0;
2320 request_info.traffic_annotation =
2321 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2322
2323 StreamRequestWaiter waiter;
2324 std::unique_ptr<HttpStreamRequest> request(
2325 session->http_stream_factory()->RequestStream(
2326 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
2327 /* enable_ip_based_pooling = */ true,
2328 /* enable_alternative_services = */ true, NetLogWithSource()));
2329
2330 waiter.WaitForStream();
2331 EXPECT_TRUE(waiter.stream_done());
2332 EXPECT_FALSE(waiter.websocket_stream());
2333 EXPECT_TRUE(waiter.stream());
2334 EXPECT_FALSE(waiter.used_proxy_info().is_direct());
2335
2336 RunUntilIdle();
2337
2338 proxy_quic_data.ExpectAllReadDataConsumed();
2339 proxy_quic_data.ExpectAllWriteDataConsumed();
2340 }
2341
2342 class HttpStreamFactoryBidirectionalQuicTest
2343 : public TestWithTaskEnvironment,
2344 public ::testing::WithParamInterface<quic::ParsedQuicVersion> {
2345 protected:
HttpStreamFactoryBidirectionalQuicTest()2346 HttpStreamFactoryBidirectionalQuicTest()
2347 : default_url_(kDefaultUrl),
2348 version_(GetParam()),
2349 client_packet_maker_(version_,
2350 quic::QuicUtils::CreateRandomConnectionId(
2351 quic_context_.random_generator()),
2352 quic_context_.clock(),
2353 "www.example.org",
2354 quic::Perspective::IS_CLIENT),
2355 server_packet_maker_(version_,
2356 quic::QuicUtils::CreateRandomConnectionId(
2357 quic_context_.random_generator()),
2358 quic_context_.clock(),
2359 "www.example.org",
2360 quic::Perspective::IS_SERVER,
2361 false),
2362 proxy_resolution_service_(
2363 ConfiguredProxyResolutionService::CreateDirect()),
2364 ssl_config_service_(std::make_unique<SSLConfigServiceDefaults>()) {
2365 FLAGS_quic_enable_http3_grease_randomness = false;
2366 quic_context_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
2367 quic::QuicEnableVersion(version_);
2368 }
2369
TearDown()2370 void TearDown() override { session_.reset(); }
2371
Initialize()2372 void Initialize() {
2373 params_.enable_quic = true;
2374 quic_context_.params()->supported_versions =
2375 quic::test::SupportedVersions(version_);
2376
2377 HttpNetworkSessionContext session_context;
2378 session_context.http_server_properties = &http_server_properties_;
2379 session_context.quic_context = &quic_context_;
2380
2381 // Load a certificate that is valid for *.example.org
2382 scoped_refptr<X509Certificate> test_cert(
2383 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
2384 EXPECT_TRUE(test_cert.get());
2385 verify_details_.cert_verify_result.verified_cert = test_cert;
2386 verify_details_.cert_verify_result.is_issued_by_known_root = true;
2387 crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
2388 crypto_client_stream_factory_.set_handshake_mode(
2389 MockCryptoClientStream::CONFIRM_HANDSHAKE);
2390 session_context.cert_verifier = &cert_verifier_;
2391 session_context.quic_crypto_client_stream_factory =
2392 &crypto_client_stream_factory_;
2393 session_context.transport_security_state = &transport_security_state_;
2394 session_context.host_resolver = &host_resolver_;
2395 session_context.proxy_resolution_service = proxy_resolution_service_.get();
2396 session_context.ssl_config_service = ssl_config_service_.get();
2397 session_context.client_socket_factory = &socket_factory_;
2398 session_ = std::make_unique<HttpNetworkSession>(params_, session_context);
2399 session_->quic_session_pool()->set_is_quic_known_to_work_on_current_network(
2400 true);
2401 }
2402
AddQuicAlternativeService(const url::SchemeHostPort & request_url,const std::string & alternative_destination)2403 void AddQuicAlternativeService(const url::SchemeHostPort& request_url,
2404 const std::string& alternative_destination) {
2405 const AlternativeService alternative_service(kProtoQUIC,
2406 alternative_destination, 443);
2407 base::Time expiration = base::Time::Now() + base::Days(1);
2408 http_server_properties_.SetQuicAlternativeService(
2409 request_url, NetworkAnonymizationKey(), alternative_service, expiration,
2410 session_->context().quic_context->params()->supported_versions);
2411 }
2412
AddQuicAlternativeService()2413 void AddQuicAlternativeService() {
2414 AddQuicAlternativeService(url::SchemeHostPort(default_url_),
2415 "www.example.org");
2416 }
2417
client_packet_maker()2418 test::QuicTestPacketMaker& client_packet_maker() {
2419 return client_packet_maker_;
2420 }
server_packet_maker()2421 test::QuicTestPacketMaker& server_packet_maker() {
2422 return server_packet_maker_;
2423 }
2424
socket_factory()2425 MockTaggingClientSocketFactory& socket_factory() { return socket_factory_; }
2426
session()2427 HttpNetworkSession* session() { return session_.get(); }
2428
2429 const GURL default_url_;
2430
GetNthClientInitiatedBidirectionalStreamId(int n)2431 quic::QuicStreamId GetNthClientInitiatedBidirectionalStreamId(int n) {
2432 return quic::test::GetNthClientInitiatedBidirectionalStreamId(
2433 version_.transport_version, n);
2434 }
2435
version() const2436 quic::ParsedQuicVersion version() const { return version_; }
2437
host_resolver()2438 MockHostResolver* host_resolver() { return &host_resolver_; }
2439
2440 private:
2441 quic::test::QuicFlagSaver saver_;
2442 const quic::ParsedQuicVersion version_;
2443 MockQuicContext quic_context_;
2444 test::QuicTestPacketMaker client_packet_maker_;
2445 test::QuicTestPacketMaker server_packet_maker_;
2446 MockTaggingClientSocketFactory socket_factory_;
2447 std::unique_ptr<HttpNetworkSession> session_;
2448 MockCertVerifier cert_verifier_;
2449 ProofVerifyDetailsChromium verify_details_;
2450 MockCryptoClientStreamFactory crypto_client_stream_factory_;
2451 HttpServerProperties http_server_properties_;
2452 TransportSecurityState transport_security_state_;
2453 MockHostResolver host_resolver_{
2454 /*default_result=*/
2455 MockHostResolverBase::RuleResolver::GetLocalhostResult()};
2456 std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
2457 std::unique_ptr<SSLConfigServiceDefaults> ssl_config_service_;
2458 HttpNetworkSessionParams params_;
2459 };
2460
2461 INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
2462 HttpStreamFactoryBidirectionalQuicTest,
2463 ::testing::ValuesIn(AllSupportedQuicVersions()),
2464 ::testing::PrintToStringParamName());
2465
TEST_P(HttpStreamFactoryBidirectionalQuicTest,RequestBidirectionalStreamImplQuicAlternative)2466 TEST_P(HttpStreamFactoryBidirectionalQuicTest,
2467 RequestBidirectionalStreamImplQuicAlternative) {
2468 MockQuicData mock_quic_data(version());
2469 // Set priority to default value so that
2470 // QuicTestPacketMaker::MakeRequestHeadersPacket() does not add mock
2471 // PRIORITY_UPDATE frame, which BidirectionalStreamQuicImpl currently does not
2472 // send.
2473 // TODO(https://crbug.com/1059250): Implement PRIORITY_UPDATE in
2474 // BidirectionalStreamQuicImpl.
2475 spdy::SpdyPriority priority =
2476 ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
2477 size_t spdy_headers_frame_length;
2478 int packet_num = 1;
2479 mock_quic_data.AddWrite(
2480 SYNCHRONOUS,
2481 client_packet_maker().MakeInitialSettingsPacket(packet_num++));
2482 mock_quic_data.AddWrite(
2483 SYNCHRONOUS,
2484 client_packet_maker().MakeRequestHeadersPacket(
2485 packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
2486 /*fin=*/true, priority,
2487 client_packet_maker().GetRequestHeaders("GET", "https", "/"),
2488 &spdy_headers_frame_length));
2489 size_t spdy_response_headers_frame_length;
2490 mock_quic_data.AddRead(
2491 ASYNC, server_packet_maker().MakeResponseHeadersPacket(
2492 1, GetNthClientInitiatedBidirectionalStreamId(0),
2493 /*fin=*/true, server_packet_maker().GetResponseHeaders("200"),
2494 &spdy_response_headers_frame_length));
2495 mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
2496 mock_quic_data.AddSocketDataToFactory(&socket_factory());
2497
2498 // Add hanging data for http job.
2499 auto hanging_data = std::make_unique<StaticSocketDataProvider>();
2500 MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
2501 hanging_data->set_connect_data(hanging_connect);
2502 socket_factory().AddSocketDataProvider(hanging_data.get());
2503 SSLSocketDataProvider ssl_data(ASYNC, OK);
2504 socket_factory().AddSSLSocketDataProvider(&ssl_data);
2505
2506 // Set up QUIC as alternative_service.
2507 Initialize();
2508 AddQuicAlternativeService();
2509
2510 // Now request a stream.
2511 HttpRequestInfo request_info;
2512 request_info.method = "GET";
2513 request_info.url = default_url_;
2514 request_info.load_flags = 0;
2515 request_info.traffic_annotation =
2516 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2517
2518 StreamRequestWaiter waiter;
2519 std::unique_ptr<HttpStreamRequest> request(
2520 session()->http_stream_factory()->RequestBidirectionalStreamImpl(
2521 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
2522 /* enable_ip_based_pooling = */ true,
2523 /* enable_alternative_services = */ true, NetLogWithSource()));
2524
2525 waiter.WaitForStream();
2526 EXPECT_TRUE(waiter.stream_done());
2527 EXPECT_FALSE(waiter.websocket_stream());
2528 ASSERT_FALSE(waiter.stream());
2529 ASSERT_TRUE(waiter.bidirectional_stream_impl());
2530 BidirectionalStreamImpl* stream_impl = waiter.bidirectional_stream_impl();
2531
2532 BidirectionalStreamRequestInfo bidi_request_info;
2533 bidi_request_info.method = "GET";
2534 bidi_request_info.url = default_url_;
2535 bidi_request_info.end_stream_on_headers = true;
2536 bidi_request_info.priority = LOWEST;
2537
2538 TestBidirectionalDelegate delegate;
2539 stream_impl->Start(&bidi_request_info, NetLogWithSource(),
2540 /*send_request_headers_automatically=*/true, &delegate,
2541 nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
2542 delegate.WaitUntilDone();
2543
2544 auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(1);
2545 EXPECT_THAT(stream_impl->ReadData(buffer.get(), 1), IsOk());
2546 EXPECT_EQ(kProtoQUIC, stream_impl->GetProtocol());
2547 EXPECT_EQ("200", delegate.response_headers().find(":status")->second);
2548 EXPECT_EQ(0,
2549 GetSocketPoolGroupCount(session()->GetSocketPool(
2550 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
2551 EXPECT_TRUE(waiter.used_proxy_info().is_direct());
2552 }
2553
2554 // Tests that if Http job fails, but Quic job succeeds, we return
2555 // BidirectionalStreamQuicImpl.
TEST_P(HttpStreamFactoryBidirectionalQuicTest,RequestBidirectionalStreamImplHttpJobFailsQuicJobSucceeds)2556 TEST_P(HttpStreamFactoryBidirectionalQuicTest,
2557 RequestBidirectionalStreamImplHttpJobFailsQuicJobSucceeds) {
2558 // Set up Quic data.
2559 MockQuicData mock_quic_data(version());
2560 // Set priority to default value so that
2561 // QuicTestPacketMaker::MakeRequestHeadersPacket() does not add mock
2562 // PRIORITY_UPDATE frame, which BidirectionalStreamQuicImpl currently does not
2563 // send.
2564 // TODO(https://crbug.com/1059250): Implement PRIORITY_UPDATE in
2565 // BidirectionalStreamQuicImpl.
2566 spdy::SpdyPriority priority =
2567 ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
2568 size_t spdy_headers_frame_length;
2569 int packet_num = 1;
2570 mock_quic_data.AddWrite(
2571 SYNCHRONOUS,
2572 client_packet_maker().MakeInitialSettingsPacket(packet_num++));
2573 mock_quic_data.AddWrite(
2574 SYNCHRONOUS,
2575 client_packet_maker().MakeRequestHeadersPacket(
2576 packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
2577 /*fin=*/true, priority,
2578 client_packet_maker().GetRequestHeaders("GET", "https", "/"),
2579 &spdy_headers_frame_length));
2580 size_t spdy_response_headers_frame_length;
2581 mock_quic_data.AddRead(
2582 ASYNC, server_packet_maker().MakeResponseHeadersPacket(
2583 1, GetNthClientInitiatedBidirectionalStreamId(0),
2584 /*fin=*/true, server_packet_maker().GetResponseHeaders("200"),
2585 &spdy_response_headers_frame_length));
2586 mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
2587 mock_quic_data.AddSocketDataToFactory(&socket_factory());
2588
2589 // Make the http job fail.
2590 auto http_job_data = std::make_unique<StaticSocketDataProvider>();
2591 MockConnect failed_connect(ASYNC, ERR_CONNECTION_REFUSED);
2592 http_job_data->set_connect_data(failed_connect);
2593 socket_factory().AddSocketDataProvider(http_job_data.get());
2594 SSLSocketDataProvider ssl_data(ASYNC, OK);
2595 socket_factory().AddSSLSocketDataProvider(&ssl_data);
2596
2597 // Set up QUIC as alternative_service.
2598 Initialize();
2599 AddQuicAlternativeService();
2600
2601 // Now request a stream.
2602 HttpRequestInfo request_info;
2603 request_info.method = "GET";
2604 request_info.url = default_url_;
2605 request_info.load_flags = 0;
2606 request_info.traffic_annotation =
2607 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2608
2609 StreamRequestWaiter waiter;
2610 std::unique_ptr<HttpStreamRequest> request(
2611 session()->http_stream_factory()->RequestBidirectionalStreamImpl(
2612 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
2613 /* enable_ip_based_pooling = */ true,
2614 /* enable_alternative_services = */ true, NetLogWithSource()));
2615
2616 waiter.WaitForStream();
2617 EXPECT_TRUE(waiter.stream_done());
2618 EXPECT_FALSE(waiter.websocket_stream());
2619 ASSERT_FALSE(waiter.stream());
2620 ASSERT_TRUE(waiter.bidirectional_stream_impl());
2621 BidirectionalStreamImpl* stream_impl = waiter.bidirectional_stream_impl();
2622
2623 BidirectionalStreamRequestInfo bidi_request_info;
2624 bidi_request_info.method = "GET";
2625 bidi_request_info.url = default_url_;
2626 bidi_request_info.end_stream_on_headers = true;
2627 bidi_request_info.priority = LOWEST;
2628
2629 TestBidirectionalDelegate delegate;
2630 stream_impl->Start(&bidi_request_info, NetLogWithSource(),
2631 /*send_request_headers_automatically=*/true, &delegate,
2632 nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
2633 delegate.WaitUntilDone();
2634
2635 // Make sure the BidirectionalStream negotiated goes through QUIC.
2636 auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(1);
2637 EXPECT_THAT(stream_impl->ReadData(buffer.get(), 1), IsOk());
2638 EXPECT_EQ(kProtoQUIC, stream_impl->GetProtocol());
2639 EXPECT_EQ("200", delegate.response_headers().find(":status")->second);
2640 // There is no Http2 socket pool.
2641 EXPECT_EQ(0,
2642 GetSocketPoolGroupCount(session()->GetSocketPool(
2643 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
2644 EXPECT_TRUE(waiter.used_proxy_info().is_direct());
2645 }
2646
TEST_F(HttpStreamFactoryTest,RequestBidirectionalStreamImplFailure)2647 TEST_F(HttpStreamFactoryTest, RequestBidirectionalStreamImplFailure) {
2648 SpdySessionDependencies session_deps(
2649 ConfiguredProxyResolutionService::CreateDirect());
2650
2651 MockRead mock_read(ASYNC, OK);
2652 SequencedSocketData socket_data(base::make_span(&mock_read, 1u),
2653 base::span<MockWrite>());
2654 socket_data.set_connect_data(MockConnect(ASYNC, OK));
2655 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
2656
2657 SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
2658
2659 // If HTTP/1 is used, BidirectionalStreamImpl should not be obtained.
2660 ssl_socket_data.next_proto = kProtoHTTP11;
2661 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
2662
2663 std::unique_ptr<HttpNetworkSession> session(
2664 SpdySessionDependencies::SpdyCreateSession(&session_deps));
2665
2666 // Now request a stream.
2667 HttpRequestInfo request_info;
2668 request_info.method = "GET";
2669 request_info.url = GURL("https://www.google.com");
2670 request_info.load_flags = 0;
2671 request_info.traffic_annotation =
2672 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2673
2674 StreamRequestWaiter waiter;
2675 std::unique_ptr<HttpStreamRequest> request(
2676 session->http_stream_factory()->RequestBidirectionalStreamImpl(
2677 request_info, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {}, &waiter,
2678 /* enable_ip_based_pooling = */ true,
2679 /* enable_alternative_services = */ true, NetLogWithSource()));
2680 waiter.WaitForStream();
2681 EXPECT_TRUE(waiter.stream_done());
2682 ASSERT_THAT(waiter.error_status(), IsError(ERR_FAILED));
2683 EXPECT_FALSE(waiter.websocket_stream());
2684 ASSERT_FALSE(waiter.stream());
2685 ASSERT_FALSE(waiter.bidirectional_stream_impl());
2686 EXPECT_EQ(1,
2687 GetSocketPoolGroupCount(session->GetSocketPool(
2688 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
2689 }
2690
2691 #if BUILDFLAG(IS_ANDROID)
2692 // Verify HttpStreamFactory::Job passes socket tag along properly and that
2693 // SpdySessions have unique socket tags (e.g. one sessions should not be shared
2694 // amongst streams with different socket tags).
TEST_F(HttpStreamFactoryTest,Tag)2695 TEST_F(HttpStreamFactoryTest, Tag) {
2696 SpdySessionDependencies session_deps;
2697 auto socket_factory = std::make_unique<MockTaggingClientSocketFactory>();
2698 auto* socket_factory_ptr = socket_factory.get();
2699 session_deps.socket_factory = std::move(socket_factory);
2700
2701 // Prepare for two HTTPS connects.
2702 MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
2703 SequencedSocketData socket_data(base::make_span(&mock_read, 1u),
2704 base::span<MockWrite>());
2705 socket_data.set_connect_data(MockConnect(ASYNC, OK));
2706 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
2707 MockRead mock_read2(SYNCHRONOUS, ERR_IO_PENDING);
2708 SequencedSocketData socket_data2(base::make_span(&mock_read2, 1u),
2709 base::span<MockWrite>());
2710 socket_data2.set_connect_data(MockConnect(ASYNC, OK));
2711 session_deps.socket_factory->AddSocketDataProvider(&socket_data2);
2712 SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
2713 ssl_socket_data.ssl_info.cert =
2714 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
2715 ssl_socket_data.next_proto = kProtoHTTP2;
2716 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
2717 SSLSocketDataProvider ssl_socket_data2(ASYNC, OK);
2718 ssl_socket_data2.ssl_info.cert =
2719 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
2720 ssl_socket_data2.next_proto = kProtoHTTP2;
2721 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data2);
2722
2723 std::unique_ptr<HttpNetworkSession> session(
2724 SpdySessionDependencies::SpdyCreateSession(&session_deps));
2725
2726 // Prepare two different tags and corresponding HttpRequestInfos.
2727 SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
2728 HttpRequestInfo request_info1;
2729 request_info1.method = "GET";
2730 request_info1.url = GURL("https://example.org");
2731 request_info1.load_flags = 0;
2732 request_info1.socket_tag = tag1;
2733 request_info1.traffic_annotation =
2734 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2735 SocketTag tag2(getuid(), 0x87654321);
2736 HttpRequestInfo request_info2 = request_info1;
2737 request_info2.socket_tag = tag2;
2738 request_info2.traffic_annotation =
2739 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2740
2741 // Verify one stream with one tag results in one session, group and
2742 // socket.
2743 StreamRequestWaiter waiter1;
2744 std::unique_ptr<HttpStreamRequest> request1(
2745 session->http_stream_factory()->RequestStream(
2746 request_info1, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
2747 &waiter1, /* enable_ip_based_pooling = */ true,
2748 /* enable_alternative_services = */ true, NetLogWithSource()));
2749 waiter1.WaitForStream();
2750 EXPECT_TRUE(waiter1.stream_done());
2751 EXPECT_TRUE(nullptr == waiter1.websocket_stream());
2752 ASSERT_TRUE(nullptr != waiter1.stream());
2753
2754 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
2755 EXPECT_EQ(1,
2756 GetSocketPoolGroupCount(session->GetSocketPool(
2757 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
2758 EXPECT_EQ(1,
2759 GetHandedOutSocketCount(session->GetSocketPool(
2760 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
2761 // Verify socket tagged appropriately.
2762 EXPECT_TRUE(tag1 == socket_factory_ptr->GetLastProducedTCPSocket()->tag());
2763 EXPECT_TRUE(socket_factory_ptr->GetLastProducedTCPSocket()
2764 ->tagged_before_connected());
2765
2766 // Verify one more stream with a different tag results in one more session and
2767 // socket.
2768 StreamRequestWaiter waiter2;
2769 std::unique_ptr<HttpStreamRequest> request2(
2770 session->http_stream_factory()->RequestStream(
2771 request_info2, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
2772 &waiter2, /* enable_ip_based_pooling = */ true,
2773 /* enable_alternative_services = */ true, NetLogWithSource()));
2774 waiter2.WaitForStream();
2775 EXPECT_TRUE(waiter2.stream_done());
2776 EXPECT_TRUE(nullptr == waiter2.websocket_stream());
2777 ASSERT_TRUE(nullptr != waiter2.stream());
2778
2779 EXPECT_EQ(2, GetSpdySessionCount(session.get()));
2780 EXPECT_EQ(1,
2781 GetSocketPoolGroupCount(session->GetSocketPool(
2782 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
2783 EXPECT_EQ(2,
2784 GetHandedOutSocketCount(session->GetSocketPool(
2785 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
2786 // Verify socket tagged appropriately.
2787 EXPECT_TRUE(tag2 == socket_factory_ptr->GetLastProducedTCPSocket()->tag());
2788 EXPECT_TRUE(socket_factory_ptr->GetLastProducedTCPSocket()
2789 ->tagged_before_connected());
2790
2791 // Verify one more stream reusing a tag does not create new sessions, groups
2792 // or sockets.
2793 StreamRequestWaiter waiter3;
2794 std::unique_ptr<HttpStreamRequest> request3(
2795 session->http_stream_factory()->RequestStream(
2796 request_info2, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
2797 &waiter3, /* enable_ip_based_pooling = */ true,
2798 /* enable_alternative_services = */ true, NetLogWithSource()));
2799 waiter3.WaitForStream();
2800 EXPECT_TRUE(waiter3.stream_done());
2801 EXPECT_TRUE(nullptr == waiter3.websocket_stream());
2802 ASSERT_TRUE(nullptr != waiter3.stream());
2803
2804 EXPECT_EQ(2, GetSpdySessionCount(session.get()));
2805 EXPECT_EQ(1,
2806 GetSocketPoolGroupCount(session->GetSocketPool(
2807 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
2808 EXPECT_EQ(2,
2809 GetHandedOutSocketCount(session->GetSocketPool(
2810 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
2811 }
2812
2813 // Verify HttpStreamFactory::Job passes socket tag along properly to QUIC
2814 // sessions and that QuicSessions have unique socket tags (e.g. one sessions
2815 // should not be shared amongst streams with different socket tags).
TEST_P(HttpStreamFactoryBidirectionalQuicTest,Tag)2816 TEST_P(HttpStreamFactoryBidirectionalQuicTest, Tag) {
2817 // Prepare mock QUIC data for a first session establishment.
2818 MockQuicData mock_quic_data(version());
2819 spdy::SpdyPriority priority =
2820 ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
2821 size_t spdy_headers_frame_length;
2822 int packet_num = 1;
2823 mock_quic_data.AddWrite(
2824 SYNCHRONOUS,
2825 client_packet_maker().MakeInitialSettingsPacket(packet_num++));
2826 mock_quic_data.AddWrite(
2827 SYNCHRONOUS,
2828 client_packet_maker().MakeRequestHeadersPacket(
2829 packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
2830 /*fin=*/true, priority,
2831 client_packet_maker().GetRequestHeaders("GET", "https", "/"),
2832 &spdy_headers_frame_length));
2833 size_t spdy_response_headers_frame_length;
2834 mock_quic_data.AddRead(
2835 ASYNC, server_packet_maker().MakeResponseHeadersPacket(
2836 1, GetNthClientInitiatedBidirectionalStreamId(0),
2837 /*fin=*/true, server_packet_maker().GetResponseHeaders("200"),
2838 &spdy_response_headers_frame_length));
2839 mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
2840 mock_quic_data.AddSocketDataToFactory(&socket_factory());
2841
2842 // Prepare mock QUIC data for a second session establishment.
2843 client_packet_maker().Reset();
2844 MockQuicData mock_quic_data2(version());
2845 packet_num = 1;
2846 mock_quic_data2.AddWrite(
2847 SYNCHRONOUS,
2848 client_packet_maker().MakeInitialSettingsPacket(packet_num++));
2849 mock_quic_data2.AddWrite(
2850 SYNCHRONOUS,
2851 client_packet_maker().MakeRequestHeadersPacket(
2852 packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
2853 /*fin=*/true, priority,
2854 client_packet_maker().GetRequestHeaders("GET", "https", "/"),
2855 &spdy_headers_frame_length));
2856 mock_quic_data2.AddRead(
2857 ASYNC, server_packet_maker().MakeResponseHeadersPacket(
2858 1, GetNthClientInitiatedBidirectionalStreamId(0),
2859 /*fin=*/true, server_packet_maker().GetResponseHeaders("200"),
2860 &spdy_response_headers_frame_length));
2861 mock_quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
2862 mock_quic_data2.AddSocketDataToFactory(&socket_factory());
2863
2864 // Add hanging data for http job.
2865 auto hanging_data = std::make_unique<StaticSocketDataProvider>();
2866 MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
2867 hanging_data->set_connect_data(hanging_connect);
2868 socket_factory().AddSocketDataProvider(hanging_data.get());
2869 SSLSocketDataProvider ssl_data(ASYNC, OK);
2870 socket_factory().AddSSLSocketDataProvider(&ssl_data);
2871
2872 // Set up QUIC as alternative_service.
2873 Initialize();
2874 AddQuicAlternativeService();
2875
2876 // Prepare two different tags and corresponding HttpRequestInfos.
2877 SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
2878 HttpRequestInfo request_info1;
2879 request_info1.method = "GET";
2880 request_info1.url = default_url_;
2881 request_info1.load_flags = 0;
2882 request_info1.socket_tag = tag1;
2883 request_info1.traffic_annotation =
2884 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2885 SocketTag tag2(getuid(), 0x87654321);
2886 HttpRequestInfo request_info2 = request_info1;
2887 request_info2.socket_tag = tag2;
2888 request_info2.traffic_annotation =
2889 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2890
2891 // Verify one stream with one tag results in one QUIC session.
2892 StreamRequestWaiter waiter1;
2893 std::unique_ptr<HttpStreamRequest> request1(
2894 session()->http_stream_factory()->RequestStream(
2895 request_info1, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
2896 &waiter1, /* enable_ip_based_pooling = */ true,
2897 /* enable_alternative_services = */ true, NetLogWithSource()));
2898 waiter1.WaitForStream();
2899 EXPECT_TRUE(waiter1.stream_done());
2900 EXPECT_TRUE(nullptr == waiter1.websocket_stream());
2901 ASSERT_TRUE(nullptr != waiter1.stream());
2902 EXPECT_EQ(kProtoQUIC, request1->negotiated_protocol());
2903 EXPECT_EQ(1, GetQuicSessionCount(session()));
2904
2905 // Verify socket tagged appropriately.
2906 EXPECT_TRUE(tag1 == socket_factory().GetLastProducedUDPSocket()->tag());
2907 EXPECT_TRUE(socket_factory()
2908 .GetLastProducedUDPSocket()
2909 ->tagged_before_data_transferred());
2910
2911 // Verify one more stream with a different tag results in one more session and
2912 // socket.
2913 StreamRequestWaiter waiter2;
2914 std::unique_ptr<HttpStreamRequest> request2(
2915 session()->http_stream_factory()->RequestStream(
2916 request_info2, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
2917 &waiter2, /* enable_ip_based_pooling = */ true,
2918 /* enable_alternative_services = */ true, NetLogWithSource()));
2919 waiter2.WaitForStream();
2920 EXPECT_TRUE(waiter2.stream_done());
2921 EXPECT_TRUE(nullptr == waiter2.websocket_stream());
2922 ASSERT_TRUE(nullptr != waiter2.stream());
2923 EXPECT_EQ(kProtoQUIC, request2->negotiated_protocol());
2924 EXPECT_EQ(2, GetQuicSessionCount(session()));
2925
2926 // Verify socket tagged appropriately.
2927 EXPECT_TRUE(tag2 == socket_factory().GetLastProducedUDPSocket()->tag());
2928 EXPECT_TRUE(socket_factory()
2929 .GetLastProducedUDPSocket()
2930 ->tagged_before_data_transferred());
2931
2932 // Verify one more stream reusing a tag does not create new sessions.
2933 StreamRequestWaiter waiter3;
2934 std::unique_ptr<HttpStreamRequest> request3(
2935 session()->http_stream_factory()->RequestStream(
2936 request_info2, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
2937 &waiter3, /* enable_ip_based_pooling = */ true,
2938 /* enable_alternative_services = */ true, NetLogWithSource()));
2939 waiter3.WaitForStream();
2940 EXPECT_TRUE(waiter3.stream_done());
2941 EXPECT_TRUE(nullptr == waiter3.websocket_stream());
2942 ASSERT_TRUE(nullptr != waiter3.stream());
2943 EXPECT_EQ(kProtoQUIC, request3->negotiated_protocol());
2944 EXPECT_EQ(2, GetQuicSessionCount(session()));
2945 }
2946
TEST_F(HttpStreamFactoryTest,ChangeSocketTag)2947 TEST_F(HttpStreamFactoryTest, ChangeSocketTag) {
2948 SpdySessionDependencies session_deps;
2949 auto socket_factory = std::make_unique<MockTaggingClientSocketFactory>();
2950 auto* socket_factory_ptr = socket_factory.get();
2951 session_deps.socket_factory = std::move(socket_factory);
2952
2953 // Prepare for two HTTPS connects.
2954 MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
2955 SequencedSocketData socket_data(base::make_span(&mock_read, 1u),
2956 base::span<MockWrite>());
2957 socket_data.set_connect_data(MockConnect(ASYNC, OK));
2958 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
2959 MockRead mock_read2(SYNCHRONOUS, ERR_IO_PENDING);
2960 SequencedSocketData socket_data2(base::make_span(&mock_read2, 1u),
2961 base::span<MockWrite>());
2962 socket_data2.set_connect_data(MockConnect(ASYNC, OK));
2963 session_deps.socket_factory->AddSocketDataProvider(&socket_data2);
2964 SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
2965 // Use cert for *.example.org
2966 ssl_socket_data.ssl_info.cert =
2967 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
2968 ssl_socket_data.next_proto = kProtoHTTP2;
2969 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
2970 SSLSocketDataProvider ssl_socket_data2(ASYNC, OK);
2971 // Use cert for *.example.org
2972 ssl_socket_data2.ssl_info.cert =
2973 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
2974 ssl_socket_data2.next_proto = kProtoHTTP2;
2975 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data2);
2976
2977 std::unique_ptr<HttpNetworkSession> session(
2978 SpdySessionDependencies::SpdyCreateSession(&session_deps));
2979
2980 // Prepare two different tags and corresponding HttpRequestInfos.
2981 SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
2982 HttpRequestInfo request_info1;
2983 request_info1.method = "GET";
2984 request_info1.url = GURL("https://www.example.org");
2985 request_info1.load_flags = 0;
2986 request_info1.socket_tag = tag1;
2987 request_info1.traffic_annotation =
2988 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2989
2990 SocketTag tag2(getuid(), 0x87654321);
2991 HttpRequestInfo request_info2 = request_info1;
2992 request_info2.socket_tag = tag2;
2993 request_info2.traffic_annotation =
2994 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2995
2996 // Prepare another HttpRequestInfo with tag1 and a different host name.
2997 HttpRequestInfo request_info3 = request_info1;
2998 request_info3.url = GURL("https://foo.example.org");
2999 request_info3.traffic_annotation =
3000 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3001
3002 // Verify one stream with one tag results in one session, group and
3003 // socket.
3004 StreamRequestWaiter waiter1;
3005 std::unique_ptr<HttpStreamRequest> request1(
3006 session->http_stream_factory()->RequestStream(
3007 request_info1, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3008 &waiter1, /* enable_ip_based_pooling = */ true,
3009 /* enable_alternative_services = */ true, NetLogWithSource()));
3010 waiter1.WaitForStream();
3011 EXPECT_TRUE(waiter1.stream_done());
3012 EXPECT_FALSE(waiter1.websocket_stream());
3013 ASSERT_TRUE(waiter1.stream());
3014
3015 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
3016 EXPECT_EQ(1,
3017 GetSocketPoolGroupCount(session->GetSocketPool(
3018 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3019 EXPECT_EQ(1,
3020 GetHandedOutSocketCount(session->GetSocketPool(
3021 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3022 // Verify socket tagged appropriately.
3023 MockTaggingStreamSocket* socket =
3024 socket_factory_ptr->GetLastProducedTCPSocket();
3025 EXPECT_TRUE(tag1 == socket->tag());
3026 EXPECT_TRUE(socket->tagged_before_connected());
3027
3028 // Verify the socket tag on the first session can be changed.
3029 StreamRequestWaiter waiter2;
3030 std::unique_ptr<HttpStreamRequest> request2(
3031 session->http_stream_factory()->RequestStream(
3032 request_info2, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3033 &waiter2, /* enable_ip_based_pooling = */ true,
3034 /* enable_alternative_services = */ true, NetLogWithSource()));
3035 waiter2.WaitForStream();
3036 EXPECT_TRUE(waiter2.stream_done());
3037 EXPECT_FALSE(waiter2.websocket_stream());
3038 ASSERT_TRUE(waiter2.stream());
3039 // Verify still have just one session.
3040 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
3041 EXPECT_EQ(1,
3042 GetSocketPoolGroupCount(session->GetSocketPool(
3043 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3044 EXPECT_EQ(1,
3045 GetHandedOutSocketCount(session->GetSocketPool(
3046 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3047 // Verify no new sockets created.
3048 EXPECT_EQ(socket, socket_factory_ptr->GetLastProducedTCPSocket());
3049 // Verify socket tag changed.
3050 EXPECT_TRUE(tag2 == socket->tag());
3051 EXPECT_FALSE(socket->tagged_before_connected());
3052
3053 // Verify attempting to use the first stream fails because the session's
3054 // socket tag has since changed.
3055 TestCompletionCallback callback1;
3056 waiter1.stream()->RegisterRequest(&request_info1);
3057 EXPECT_EQ(ERR_FAILED, waiter1.stream()->InitializeStream(
3058 /* can_send_early = */ false, DEFAULT_PRIORITY,
3059 NetLogWithSource(), callback1.callback()));
3060
3061 // Verify the socket tag can be changed, this time using an IP alias
3062 // (different host, same IP).
3063 StreamRequestWaiter waiter3;
3064 std::unique_ptr<HttpStreamRequest> request3(
3065 session->http_stream_factory()->RequestStream(
3066 request_info3, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3067 &waiter3, /* enable_ip_based_pooling = */ true,
3068 /* enable_alternative_services = */ true, NetLogWithSource()));
3069 waiter3.WaitForStream();
3070 EXPECT_TRUE(waiter3.stream_done());
3071 EXPECT_FALSE(waiter3.websocket_stream());
3072 ASSERT_TRUE(waiter3.stream());
3073 // Verify still have just one session.
3074 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
3075 EXPECT_EQ(1,
3076 GetSocketPoolGroupCount(session->GetSocketPool(
3077 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3078 EXPECT_EQ(1,
3079 GetHandedOutSocketCount(session->GetSocketPool(
3080 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3081 // Verify no new sockets created.
3082 EXPECT_EQ(socket, socket_factory_ptr->GetLastProducedTCPSocket());
3083 // Verify socket tag changed.
3084 EXPECT_TRUE(tag1 == socket->tag());
3085 EXPECT_FALSE(socket->tagged_before_connected());
3086
3087 // Initialize the third stream, thus marking the session active, so it cannot
3088 // have its socket tag changed.
3089 TestCompletionCallback callback3;
3090 waiter3.stream()->RegisterRequest(&request_info3);
3091 EXPECT_EQ(OK, waiter3.stream()->InitializeStream(
3092 /* can_send_early = */ false, DEFAULT_PRIORITY,
3093 NetLogWithSource(), callback3.callback()));
3094
3095 // Verify a new session is created when a request with a different tag is
3096 // started.
3097 StreamRequestWaiter waiter4;
3098 std::unique_ptr<HttpStreamRequest> request4(
3099 session->http_stream_factory()->RequestStream(
3100 request_info2, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3101 &waiter4, /* enable_ip_based_pooling = */ true,
3102 /* enable_alternative_services = */ true, NetLogWithSource()));
3103 waiter4.WaitForStream();
3104 EXPECT_TRUE(waiter4.stream_done());
3105 EXPECT_FALSE(waiter4.websocket_stream());
3106 ASSERT_TRUE(waiter4.stream());
3107 // Verify we now have two sessions.
3108 EXPECT_EQ(2, GetSpdySessionCount(session.get()));
3109 EXPECT_EQ(1,
3110 GetSocketPoolGroupCount(session->GetSocketPool(
3111 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3112 EXPECT_EQ(2,
3113 GetHandedOutSocketCount(session->GetSocketPool(
3114 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3115 // Verify a new socket was created.
3116 MockTaggingStreamSocket* socket2 =
3117 socket_factory_ptr->GetLastProducedTCPSocket();
3118 EXPECT_NE(socket, socket2);
3119 // Verify tag set appropriately.
3120 EXPECT_TRUE(tag2 == socket2->tag());
3121 EXPECT_TRUE(socket2->tagged_before_connected());
3122 // Verify tag on original socket is unchanged.
3123 EXPECT_TRUE(tag1 == socket->tag());
3124
3125 waiter3.stream()->Close(/* not_reusable = */ true);
3126 }
3127
3128 // Regression test for https://crbug.com/954503.
TEST_F(HttpStreamFactoryTest,ChangeSocketTagAvoidOverwrite)3129 TEST_F(HttpStreamFactoryTest, ChangeSocketTagAvoidOverwrite) {
3130 SpdySessionDependencies session_deps;
3131 auto socket_factory = std::make_unique<MockTaggingClientSocketFactory>();
3132 auto* socket_factory_ptr = socket_factory.get();
3133 session_deps.socket_factory = std::move(socket_factory);
3134
3135 // Prepare for two HTTPS connects.
3136 MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
3137 SequencedSocketData socket_data(base::make_span(&mock_read, 1u),
3138 base::span<MockWrite>());
3139 socket_data.set_connect_data(MockConnect(ASYNC, OK));
3140 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
3141 MockRead mock_read2(SYNCHRONOUS, ERR_IO_PENDING);
3142 SequencedSocketData socket_data2(base::make_span(&mock_read2, 1u),
3143 base::span<MockWrite>());
3144 socket_data2.set_connect_data(MockConnect(ASYNC, OK));
3145 session_deps.socket_factory->AddSocketDataProvider(&socket_data2);
3146 SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
3147 // Use cert for *.example.org
3148 ssl_socket_data.ssl_info.cert =
3149 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
3150 ssl_socket_data.next_proto = kProtoHTTP2;
3151 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
3152 SSLSocketDataProvider ssl_socket_data2(ASYNC, OK);
3153 // Use cert for *.example.org
3154 ssl_socket_data2.ssl_info.cert =
3155 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
3156 ssl_socket_data2.next_proto = kProtoHTTP2;
3157 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data2);
3158
3159 std::unique_ptr<HttpNetworkSession> session(
3160 SpdySessionDependencies::SpdyCreateSession(&session_deps));
3161
3162 // Prepare three different tags and corresponding HttpRequestInfos.
3163 SocketTag tag1(SocketTag::UNSET_UID, 2);
3164 HttpRequestInfo request_info1;
3165 request_info1.method = "GET";
3166 request_info1.url = GURL("https://www.example.org");
3167 request_info1.load_flags = 0;
3168 request_info1.socket_tag = tag1;
3169 request_info1.traffic_annotation =
3170 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3171
3172 SocketTag tag2(SocketTag::UNSET_UID, 1);
3173 HttpRequestInfo request_info2 = request_info1;
3174 request_info2.socket_tag = tag2;
3175
3176 HttpRequestInfo request_info3 = request_info1;
3177 SocketTag tag3(SocketTag::UNSET_UID, 3);
3178 request_info3.socket_tag = tag3;
3179
3180 // Prepare another HttpRequestInfo with tag3 and a different host name.
3181 HttpRequestInfo request_info4 = request_info1;
3182 request_info4.socket_tag = tag3;
3183 request_info4.url = GURL("https://foo.example.org");
3184
3185 // Verify one stream with one tag results in one session, group and
3186 // socket.
3187 StreamRequestWaiter waiter1;
3188 std::unique_ptr<HttpStreamRequest> request1(
3189 session->http_stream_factory()->RequestStream(
3190 request_info1, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3191 &waiter1, /* enable_ip_based_pooling = */ true,
3192 /* enable_alternative_services = */ true, NetLogWithSource()));
3193 waiter1.WaitForStream();
3194 EXPECT_TRUE(waiter1.stream_done());
3195 EXPECT_FALSE(waiter1.websocket_stream());
3196 ASSERT_TRUE(waiter1.stream());
3197
3198 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
3199 EXPECT_EQ(1,
3200 GetSocketPoolGroupCount(session->GetSocketPool(
3201 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3202 EXPECT_EQ(1,
3203 GetHandedOutSocketCount(session->GetSocketPool(
3204 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3205 // Verify socket tagged appropriately.
3206 MockTaggingStreamSocket* socket =
3207 socket_factory_ptr->GetLastProducedTCPSocket();
3208 EXPECT_TRUE(tag1 == socket->tag());
3209 EXPECT_TRUE(socket->tagged_before_connected());
3210
3211 // Initialize the first stream, thus marking the session active, so it cannot
3212 // have its socket tag changed and be reused for the second session.
3213 TestCompletionCallback callback1;
3214 waiter1.stream()->RegisterRequest(&request_info1);
3215 EXPECT_EQ(OK, waiter1.stream()->InitializeStream(
3216 /* can_send_early = */ false, DEFAULT_PRIORITY,
3217 NetLogWithSource(), callback1.callback()));
3218
3219 // Create a second stream with a new tag.
3220 StreamRequestWaiter waiter2;
3221 std::unique_ptr<HttpStreamRequest> request2(
3222 session->http_stream_factory()->RequestStream(
3223 request_info2, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3224 &waiter2, /* enable_ip_based_pooling = */ true,
3225 /* enable_alternative_services = */ true, NetLogWithSource()));
3226 waiter2.WaitForStream();
3227 EXPECT_TRUE(waiter2.stream_done());
3228 EXPECT_FALSE(waiter2.websocket_stream());
3229 ASSERT_TRUE(waiter2.stream());
3230 // Verify we now have two sessions.
3231 EXPECT_EQ(2, GetSpdySessionCount(session.get()));
3232 EXPECT_EQ(1,
3233 GetSocketPoolGroupCount(session->GetSocketPool(
3234 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3235 EXPECT_EQ(2,
3236 GetHandedOutSocketCount(session->GetSocketPool(
3237 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3238 // Verify a new socket was created.
3239 MockTaggingStreamSocket* socket2 =
3240 socket_factory_ptr->GetLastProducedTCPSocket();
3241 EXPECT_NE(socket, socket2);
3242 // Verify tag set appropriately.
3243 EXPECT_TRUE(tag2 == socket2->tag());
3244 EXPECT_TRUE(socket2->tagged_before_connected());
3245 // Verify tag on original socket is unchanged.
3246 EXPECT_TRUE(tag1 == socket->tag());
3247
3248 // Initialize the second stream, thus marking the session active, so it cannot
3249 // have its socket tag changed and be reused for the third session.
3250 TestCompletionCallback callback2;
3251 waiter2.stream()->RegisterRequest(&request_info2);
3252 EXPECT_EQ(OK, waiter2.stream()->InitializeStream(
3253 /* can_send_early = */ false, DEFAULT_PRIORITY,
3254 NetLogWithSource(), callback2.callback()));
3255
3256 // Release first stream so first session can be retagged for third request.
3257 waiter1.stream()->Close(/* not_reusable = */ true);
3258
3259 // Verify the first session can be retagged for a third request.
3260 StreamRequestWaiter waiter3;
3261 std::unique_ptr<HttpStreamRequest> request3(
3262 session->http_stream_factory()->RequestStream(
3263 request_info3, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3264 &waiter3, /* enable_ip_based_pooling = */ true,
3265 /* enable_alternative_services = */ true, NetLogWithSource()));
3266 waiter3.WaitForStream();
3267 EXPECT_TRUE(waiter3.stream_done());
3268 EXPECT_FALSE(waiter3.websocket_stream());
3269 ASSERT_TRUE(waiter3.stream());
3270 // Verify still have two sessions.
3271 EXPECT_EQ(2, GetSpdySessionCount(session.get()));
3272 EXPECT_EQ(1,
3273 GetSocketPoolGroupCount(session->GetSocketPool(
3274 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3275 EXPECT_EQ(2,
3276 GetHandedOutSocketCount(session->GetSocketPool(
3277 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3278 // Verify no new sockets created.
3279 EXPECT_EQ(socket2, socket_factory_ptr->GetLastProducedTCPSocket());
3280 // Verify socket tag changed.
3281 EXPECT_TRUE(tag3 == socket->tag());
3282 EXPECT_FALSE(socket->tagged_before_connected());
3283
3284 // Release second stream so second session can be retagged for fourth request.
3285 waiter2.stream()->Close(/* not_reusable = */ true);
3286
3287 // Request a stream with a new tag and a different host that aliases existing
3288 // sessions.
3289 StreamRequestWaiter waiter4;
3290 std::unique_ptr<HttpStreamRequest> request4(
3291 session->http_stream_factory()->RequestStream(
3292 request_info4, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3293 &waiter4, /* enable_ip_based_pooling = */ true,
3294 /* enable_alternative_services = */ true, NetLogWithSource()));
3295 waiter4.WaitForStream();
3296 EXPECT_TRUE(waiter4.stream_done());
3297 EXPECT_FALSE(waiter4.websocket_stream());
3298 ASSERT_TRUE(waiter4.stream());
3299 // Verify no new sockets created.
3300 EXPECT_EQ(socket2, socket_factory_ptr->GetLastProducedTCPSocket());
3301 }
3302 #endif
3303
3304 // Test that when creating a stream all sessions that alias an IP are tried,
3305 // not just one. This is important because there can be multiple sessions
3306 // that could satisfy a stream request and they should all be tried.
TEST_F(HttpStreamFactoryTest,MultiIPAliases)3307 TEST_F(HttpStreamFactoryTest, MultiIPAliases) {
3308 SpdySessionDependencies session_deps;
3309
3310 // Prepare for two HTTPS connects.
3311 MockRead mock_read1(SYNCHRONOUS, ERR_IO_PENDING);
3312 SequencedSocketData socket_data1(base::make_span(&mock_read1, 1u),
3313 base::span<MockWrite>());
3314 socket_data1.set_connect_data(MockConnect(ASYNC, OK));
3315 session_deps.socket_factory->AddSocketDataProvider(&socket_data1);
3316 MockRead mock_read2(SYNCHRONOUS, ERR_IO_PENDING);
3317 SequencedSocketData socket_data2(base::make_span(&mock_read2, 1u),
3318 base::span<MockWrite>());
3319 socket_data2.set_connect_data(MockConnect(ASYNC, OK));
3320 session_deps.socket_factory->AddSocketDataProvider(&socket_data2);
3321 SSLSocketDataProvider ssl_socket_data1(ASYNC, OK);
3322 // Load cert for *.example.org
3323 ssl_socket_data1.ssl_info.cert =
3324 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
3325 ssl_socket_data1.next_proto = kProtoHTTP2;
3326 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data1);
3327 SSLSocketDataProvider ssl_socket_data2(ASYNC, OK);
3328 // Load cert for *.example.org
3329 ssl_socket_data2.ssl_info.cert =
3330 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
3331 ssl_socket_data2.next_proto = kProtoHTTP2;
3332 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data2);
3333
3334 std::unique_ptr<HttpNetworkSession> session(
3335 SpdySessionDependencies::SpdyCreateSession(&session_deps));
3336
3337 // Create two HttpRequestInfos, differing only in host name.
3338 // Both will resolve to 127.0.0.1 and hence be IP aliases.
3339 HttpRequestInfo request_info1;
3340 request_info1.method = "GET";
3341 request_info1.url = GURL("https://a.example.org");
3342 request_info1.privacy_mode = PRIVACY_MODE_DISABLED;
3343 request_info1.traffic_annotation =
3344 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3345 HttpRequestInfo request_info1_alias = request_info1;
3346 request_info1.url = GURL("https://b.example.org");
3347
3348 // Create two more HttpRequestInfos but with different privacy_mode.
3349 HttpRequestInfo request_info2;
3350 request_info2.method = "GET";
3351 request_info2.url = GURL("https://a.example.org");
3352 request_info2.privacy_mode = PRIVACY_MODE_ENABLED;
3353 request_info2.traffic_annotation =
3354 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3355 HttpRequestInfo request_info2_alias = request_info2;
3356 request_info2.url = GURL("https://b.example.org");
3357
3358 // Open one session.
3359 StreamRequestWaiter waiter1;
3360 std::unique_ptr<HttpStreamRequest> request1(
3361 session->http_stream_factory()->RequestStream(
3362 request_info1, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3363 &waiter1, /* enable_ip_based_pooling = */ true,
3364 /* enable_alternative_services = */ true, NetLogWithSource()));
3365 waiter1.WaitForStream();
3366 EXPECT_TRUE(waiter1.stream_done());
3367 EXPECT_FALSE(waiter1.websocket_stream());
3368 ASSERT_TRUE(waiter1.stream());
3369
3370 // Verify just one session created.
3371 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
3372 EXPECT_EQ(1,
3373 GetSocketPoolGroupCount(session->GetSocketPool(
3374 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3375 EXPECT_EQ(1,
3376 GetHandedOutSocketCount(session->GetSocketPool(
3377 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3378
3379 // Open another session to same IP but with different privacy mode.
3380 StreamRequestWaiter waiter2;
3381 std::unique_ptr<HttpStreamRequest> request2(
3382 session->http_stream_factory()->RequestStream(
3383 request_info2, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3384 &waiter2, /* enable_ip_based_pooling = */ true,
3385 /* enable_alternative_services = */ true, NetLogWithSource()));
3386 waiter2.WaitForStream();
3387 EXPECT_TRUE(waiter2.stream_done());
3388 EXPECT_FALSE(waiter2.websocket_stream());
3389 ASSERT_TRUE(waiter2.stream());
3390
3391 // Verify two sessions are now open.
3392 EXPECT_EQ(2, GetSpdySessionCount(session.get()));
3393 EXPECT_EQ(2,
3394 GetSocketPoolGroupCount(session->GetSocketPool(
3395 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3396 EXPECT_EQ(2,
3397 GetHandedOutSocketCount(session->GetSocketPool(
3398 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3399
3400 // Open a third session that IP aliases first session.
3401 StreamRequestWaiter waiter3;
3402 std::unique_ptr<HttpStreamRequest> request3(
3403 session->http_stream_factory()->RequestStream(
3404 request_info1_alias, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3405 &waiter3, /* enable_ip_based_pooling = */ true,
3406 /* enable_alternative_services = */ true, NetLogWithSource()));
3407 waiter3.WaitForStream();
3408 EXPECT_TRUE(waiter3.stream_done());
3409 EXPECT_FALSE(waiter3.websocket_stream());
3410 ASSERT_TRUE(waiter3.stream());
3411
3412 // Verify the session pool reused the first session and no new session is
3413 // created. This will fail unless the session pool supports multiple
3414 // sessions aliasing a single IP.
3415 EXPECT_EQ(2, GetSpdySessionCount(session.get()));
3416 EXPECT_EQ(2,
3417 GetSocketPoolGroupCount(session->GetSocketPool(
3418 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3419 EXPECT_EQ(2,
3420 GetHandedOutSocketCount(session->GetSocketPool(
3421 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3422
3423 // Open a fourth session that IP aliases the second session.
3424 StreamRequestWaiter waiter4;
3425 std::unique_ptr<HttpStreamRequest> request4(
3426 session->http_stream_factory()->RequestStream(
3427 request_info2_alias, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3428 &waiter4, /* enable_ip_based_pooling = */ true,
3429 /* enable_alternative_services = */ true, NetLogWithSource()));
3430 waiter4.WaitForStream();
3431 EXPECT_TRUE(waiter4.stream_done());
3432 EXPECT_FALSE(waiter4.websocket_stream());
3433 ASSERT_TRUE(waiter4.stream());
3434
3435 // Verify the session pool reused the second session. This will fail unless
3436 // the session pool supports multiple sessions aliasing a single IP.
3437 EXPECT_EQ(2, GetSpdySessionCount(session.get()));
3438 EXPECT_EQ(2,
3439 GetSocketPoolGroupCount(session->GetSocketPool(
3440 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3441 EXPECT_EQ(2,
3442 GetHandedOutSocketCount(session->GetSocketPool(
3443 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3444 }
3445
TEST_F(HttpStreamFactoryTest,SpdyIPPoolingWithDnsAliases)3446 TEST_F(HttpStreamFactoryTest, SpdyIPPoolingWithDnsAliases) {
3447 SpdySessionDependencies session_deps;
3448
3449 const std::set<std::string> kDnsAliasesA({"alias1", "alias2"});
3450 const std::set<std::string> kDnsAliasesB({"b.com", "b.org", "b.net"});
3451 const std::string kHostnameC("c.example.org");
3452
3453 session_deps.host_resolver->rules()->AddIPLiteralRuleWithDnsAliases(
3454 "a.example.org", "127.0.0.1", kDnsAliasesA);
3455 session_deps.host_resolver->rules()->AddIPLiteralRuleWithDnsAliases(
3456 "b.example.org", "127.0.0.1", kDnsAliasesB);
3457 session_deps.host_resolver->rules()->AddIPLiteralRuleWithDnsAliases(
3458 "c.example.org", "127.0.0.1", /*dns_aliases=*/std::set<std::string>());
3459
3460 // Prepare for an HTTPS connect.
3461 MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING);
3462 SequencedSocketData socket_data(base::make_span(&mock_read, 1u),
3463 base::span<MockWrite>());
3464 socket_data.set_connect_data(MockConnect(ASYNC, OK));
3465 session_deps.socket_factory->AddSocketDataProvider(&socket_data);
3466 SSLSocketDataProvider ssl_socket_data(ASYNC, OK);
3467 // Load cert for *.example.org
3468 ssl_socket_data.ssl_info.cert =
3469 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
3470 ssl_socket_data.next_proto = kProtoHTTP2;
3471 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data);
3472
3473 std::unique_ptr<HttpNetworkSession> session(
3474 SpdySessionDependencies::SpdyCreateSession(&session_deps));
3475
3476 // Create three HttpRequestInfos, differing only in host name.
3477 // All three will resolve to 127.0.0.1 and hence be IP aliases.
3478 HttpRequestInfo request_info_a;
3479 request_info_a.method = "GET";
3480 request_info_a.url = GURL("https://a.example.org");
3481 request_info_a.privacy_mode = PRIVACY_MODE_DISABLED;
3482 request_info_a.traffic_annotation =
3483 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3484 HttpRequestInfo request_info_b = request_info_a;
3485 HttpRequestInfo request_info_c = request_info_a;
3486 request_info_b.url = GURL("https://b.example.org");
3487 request_info_c.url = GURL("https://c.example.org");
3488
3489 // Open one session.
3490 StreamRequestWaiter waiter1;
3491 std::unique_ptr<HttpStreamRequest> request1(
3492 session->http_stream_factory()->RequestStream(
3493 request_info_a, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3494 &waiter1, /* enable_ip_based_pooling = */ true,
3495 /* enable_alternative_services = */ true, NetLogWithSource()));
3496 waiter1.WaitForStream();
3497 EXPECT_TRUE(waiter1.stream_done());
3498 EXPECT_FALSE(waiter1.websocket_stream());
3499 ASSERT_TRUE(waiter1.stream());
3500 EXPECT_EQ(kDnsAliasesA, waiter1.stream()->GetDnsAliases());
3501
3502 // Verify just one session created.
3503 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
3504 EXPECT_EQ(1,
3505 GetSocketPoolGroupCount(session->GetSocketPool(
3506 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3507 EXPECT_EQ(1,
3508 GetHandedOutSocketCount(session->GetSocketPool(
3509 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3510
3511 // Open a session that IP aliases first session.
3512 StreamRequestWaiter waiter2;
3513 std::unique_ptr<HttpStreamRequest> request2(
3514 session->http_stream_factory()->RequestStream(
3515 request_info_b, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3516 &waiter2, /* enable_ip_based_pooling = */ true,
3517 /* enable_alternative_services = */ true, NetLogWithSource()));
3518 waiter2.WaitForStream();
3519 EXPECT_TRUE(waiter2.stream_done());
3520 EXPECT_FALSE(waiter2.websocket_stream());
3521 ASSERT_TRUE(waiter2.stream());
3522 EXPECT_EQ(kDnsAliasesB, waiter2.stream()->GetDnsAliases());
3523
3524 // Verify the session pool reused the first session and no new session is
3525 // created. This will fail unless the session pool supports multiple
3526 // sessions aliasing a single IP.
3527 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
3528 EXPECT_EQ(1,
3529 GetSocketPoolGroupCount(session->GetSocketPool(
3530 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3531 EXPECT_EQ(1,
3532 GetHandedOutSocketCount(session->GetSocketPool(
3533 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3534
3535 // Open another session that IP aliases the first session.
3536 StreamRequestWaiter waiter3;
3537 std::unique_ptr<HttpStreamRequest> request3(
3538 session->http_stream_factory()->RequestStream(
3539 request_info_c, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3540 &waiter3, /* enable_ip_based_pooling = */ true,
3541 /* enable_alternative_services = */ true, NetLogWithSource()));
3542 waiter3.WaitForStream();
3543 EXPECT_TRUE(waiter3.stream_done());
3544 EXPECT_FALSE(waiter3.websocket_stream());
3545 ASSERT_TRUE(waiter3.stream());
3546 EXPECT_THAT(waiter3.stream()->GetDnsAliases(), ElementsAre(kHostnameC));
3547
3548 // Verify the session pool reused the first session and no new session is
3549 // created. This will fail unless the session pool supports multiple
3550 // sessions aliasing a single IP.
3551 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
3552 EXPECT_EQ(1,
3553 GetSocketPoolGroupCount(session->GetSocketPool(
3554 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3555 EXPECT_EQ(1,
3556 GetHandedOutSocketCount(session->GetSocketPool(
3557 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3558
3559 // Clear host resolver rules to ensure that cached values for DNS aliases
3560 // are used.
3561 session_deps.host_resolver->rules()->ClearRules();
3562
3563 // Re-request the original resource using `request_info_a`, which had
3564 // non-default DNS aliases.
3565 std::unique_ptr<HttpStreamRequest> request4(
3566 session->http_stream_factory()->RequestStream(
3567 request_info_a, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3568 &waiter1, /* enable_ip_based_pooling = */ true,
3569 /* enable_alternative_services = */ true, NetLogWithSource()));
3570 waiter1.WaitForStream();
3571 EXPECT_TRUE(waiter1.stream_done());
3572 EXPECT_FALSE(waiter1.websocket_stream());
3573 ASSERT_TRUE(waiter1.stream());
3574 EXPECT_EQ(kDnsAliasesA, waiter1.stream()->GetDnsAliases());
3575
3576 // Verify the session pool reused the first session and no new session is
3577 // created.
3578 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
3579 EXPECT_EQ(1,
3580 GetSocketPoolGroupCount(session->GetSocketPool(
3581 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3582 EXPECT_EQ(1,
3583 GetHandedOutSocketCount(session->GetSocketPool(
3584 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3585
3586 // Re-request a resource using `request_info_b`, which had non-default DNS
3587 // aliases.
3588 std::unique_ptr<HttpStreamRequest> request5(
3589 session->http_stream_factory()->RequestStream(
3590 request_info_b, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3591 &waiter2, /* enable_ip_based_pooling = */ true,
3592 /* enable_alternative_services = */ true, NetLogWithSource()));
3593 waiter2.WaitForStream();
3594 EXPECT_TRUE(waiter2.stream_done());
3595 EXPECT_FALSE(waiter2.websocket_stream());
3596 ASSERT_TRUE(waiter2.stream());
3597 EXPECT_EQ(kDnsAliasesB, waiter2.stream()->GetDnsAliases());
3598
3599 // Verify the session pool reused the first session and no new session is
3600 // created. This will fail unless the session pool supports multiple
3601 // sessions aliasing a single IP.
3602 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
3603 EXPECT_EQ(1,
3604 GetSocketPoolGroupCount(session->GetSocketPool(
3605 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3606 EXPECT_EQ(1,
3607 GetHandedOutSocketCount(session->GetSocketPool(
3608 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3609
3610 // Re-request a resource using `request_info_c`, which had only the default
3611 // DNS alias (the host name).
3612 std::unique_ptr<HttpStreamRequest> request6(
3613 session->http_stream_factory()->RequestStream(
3614 request_info_c, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3615 &waiter3, /* enable_ip_based_pooling = */ true,
3616 /* enable_alternative_services = */ true, NetLogWithSource()));
3617 waiter3.WaitForStream();
3618 EXPECT_TRUE(waiter3.stream_done());
3619 EXPECT_FALSE(waiter3.websocket_stream());
3620 ASSERT_TRUE(waiter3.stream());
3621 EXPECT_THAT(waiter3.stream()->GetDnsAliases(), ElementsAre(kHostnameC));
3622
3623 // Verify the session pool reused the first session and no new session is
3624 // created. This will fail unless the session pool supports multiple
3625 // sessions aliasing a single IP.
3626 EXPECT_EQ(1, GetSpdySessionCount(session.get()));
3627 EXPECT_EQ(1,
3628 GetSocketPoolGroupCount(session->GetSocketPool(
3629 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3630 EXPECT_EQ(1,
3631 GetHandedOutSocketCount(session->GetSocketPool(
3632 HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct())));
3633 }
3634
TEST_P(HttpStreamFactoryBidirectionalQuicTest,QuicIPPoolingWithDnsAliases)3635 TEST_P(HttpStreamFactoryBidirectionalQuicTest, QuicIPPoolingWithDnsAliases) {
3636 const GURL kUrlA("https://a.example.org");
3637 const GURL kUrlB("https://b.example.org");
3638 const GURL kUrlC("https://c.example.org");
3639 const std::set<std::string> kDnsAliasesA({"alias1", "alias2"});
3640 const std::set<std::string> kDnsAliasesB({"b.com", "b.org", "b.net"});
3641
3642 host_resolver()->rules()->AddIPLiteralRuleWithDnsAliases(
3643 kUrlA.host(), "127.0.0.1", kDnsAliasesA);
3644 host_resolver()->rules()->AddIPLiteralRuleWithDnsAliases(
3645 kUrlB.host(), "127.0.0.1", kDnsAliasesB);
3646 host_resolver()->rules()->AddIPLiteralRuleWithDnsAliases(
3647 kUrlC.host(), "127.0.0.1",
3648 /*dns_aliases=*/std::set<std::string>());
3649
3650 // Prepare mock QUIC data for a first session establishment.
3651 MockQuicData mock_quic_data(version());
3652 spdy::SpdyPriority priority =
3653 ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
3654 size_t spdy_headers_frame_length;
3655 int packet_num = 1;
3656 mock_quic_data.AddWrite(
3657 SYNCHRONOUS,
3658 client_packet_maker().MakeInitialSettingsPacket(packet_num++));
3659 mock_quic_data.AddWrite(
3660 SYNCHRONOUS,
3661 client_packet_maker().MakeRequestHeadersPacket(
3662 packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
3663 /*fin=*/true, priority,
3664 client_packet_maker().GetRequestHeaders("GET", "https", "/"),
3665 &spdy_headers_frame_length));
3666 size_t spdy_response_headers_frame_length;
3667 mock_quic_data.AddRead(
3668 ASYNC, server_packet_maker().MakeResponseHeadersPacket(
3669 1, GetNthClientInitiatedBidirectionalStreamId(0),
3670 /*fin=*/true, server_packet_maker().GetResponseHeaders("200"),
3671 &spdy_response_headers_frame_length));
3672 mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
3673 mock_quic_data.AddSocketDataToFactory(&socket_factory());
3674
3675 // Add hanging data for http job.
3676 auto hanging_data = std::make_unique<StaticSocketDataProvider>();
3677 MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
3678 hanging_data->set_connect_data(hanging_connect);
3679 socket_factory().AddSocketDataProvider(hanging_data.get());
3680 SSLSocketDataProvider ssl_data(ASYNC, OK);
3681 socket_factory().AddSSLSocketDataProvider(&ssl_data);
3682
3683 // Set up QUIC as alternative_service.
3684 Initialize();
3685 AddQuicAlternativeService(url::SchemeHostPort(kUrlA), kUrlA.host());
3686 AddQuicAlternativeService(url::SchemeHostPort(kUrlB), kUrlB.host());
3687 AddQuicAlternativeService(url::SchemeHostPort(kUrlC), kUrlC.host());
3688
3689 // Create three HttpRequestInfos, differing only in host name.
3690 // All three will resolve to 127.0.0.1 and hence be IP aliases.
3691 HttpRequestInfo request_info_a;
3692 request_info_a.method = "GET";
3693 request_info_a.url = kUrlA;
3694 request_info_a.privacy_mode = PRIVACY_MODE_DISABLED;
3695 request_info_a.traffic_annotation =
3696 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3697 HttpRequestInfo request_info_b = request_info_a;
3698 HttpRequestInfo request_info_c = request_info_a;
3699 request_info_b.url = kUrlB;
3700 request_info_c.url = kUrlC;
3701
3702 // Open one session.
3703 StreamRequestWaiter waiter1;
3704 std::unique_ptr<HttpStreamRequest> request1(
3705 session()->http_stream_factory()->RequestStream(
3706 request_info_a, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3707 &waiter1, /* enable_ip_based_pooling = */ true,
3708 /* enable_alternative_services = */ true, NetLogWithSource()));
3709 waiter1.WaitForStream();
3710 EXPECT_TRUE(waiter1.stream_done());
3711 EXPECT_FALSE(waiter1.websocket_stream());
3712 ASSERT_TRUE(waiter1.stream());
3713 EXPECT_EQ(kDnsAliasesA, waiter1.stream()->GetDnsAliases());
3714
3715 // Verify just one session created.
3716 EXPECT_EQ(1, GetQuicSessionCount(session()));
3717 EXPECT_EQ(kProtoQUIC, request1->negotiated_protocol());
3718
3719 // Create a request that will alias and reuse the first session.
3720 StreamRequestWaiter waiter2;
3721 std::unique_ptr<HttpStreamRequest> request2(
3722 session()->http_stream_factory()->RequestStream(
3723 request_info_b, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3724 &waiter2, /* enable_ip_based_pooling = */ true,
3725 /* enable_alternative_services = */ true, NetLogWithSource()));
3726 waiter2.WaitForStream();
3727 EXPECT_TRUE(waiter2.stream_done());
3728 EXPECT_FALSE(waiter2.websocket_stream());
3729 ASSERT_TRUE(waiter2.stream());
3730 EXPECT_EQ(kDnsAliasesB, waiter2.stream()->GetDnsAliases());
3731
3732 // Verify the session pool reused the first session and no new session is
3733 // created. This will fail unless the session pool supports multiple
3734 // sessions aliasing a single IP.
3735 EXPECT_EQ(1, GetQuicSessionCount(session()));
3736 EXPECT_EQ(kProtoQUIC, request2->negotiated_protocol());
3737
3738 // Create another request that will alias and reuse the first session.
3739 StreamRequestWaiter waiter3;
3740 std::unique_ptr<HttpStreamRequest> request3(
3741 session()->http_stream_factory()->RequestStream(
3742 request_info_c, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3743 &waiter3, /* enable_ip_based_pooling = */ true,
3744 /* enable_alternative_services = */ true, NetLogWithSource()));
3745 waiter3.WaitForStream();
3746 EXPECT_TRUE(waiter3.stream_done());
3747 EXPECT_FALSE(waiter3.websocket_stream());
3748 ASSERT_TRUE(waiter3.stream());
3749 EXPECT_THAT(waiter3.stream()->GetDnsAliases(), ElementsAre(kUrlC.host()));
3750
3751 // Clear the host resolve rules to ensure that we are using cached info.
3752 host_resolver()->rules()->ClearRules();
3753
3754 // Verify the session pool reused the first session and no new session is
3755 // created. This will fail unless the session pool supports multiple
3756 // sessions aliasing a single IP.
3757 EXPECT_EQ(1, GetQuicSessionCount(session()));
3758 EXPECT_EQ(kProtoQUIC, request3->negotiated_protocol());
3759
3760 // Create a request that will reuse the first session.
3761 std::unique_ptr<HttpStreamRequest> request4(
3762 session()->http_stream_factory()->RequestStream(
3763 request_info_a, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3764 &waiter1, /* enable_ip_based_pooling = */ true,
3765 /* enable_alternative_services = */ true, NetLogWithSource()));
3766 waiter1.WaitForStream();
3767 EXPECT_TRUE(waiter1.stream_done());
3768 EXPECT_FALSE(waiter1.websocket_stream());
3769 ASSERT_TRUE(waiter1.stream());
3770 EXPECT_EQ(kDnsAliasesA, waiter1.stream()->GetDnsAliases());
3771
3772 // Verify the session pool reused the first session and no new session is
3773 // created.
3774 EXPECT_EQ(1, GetQuicSessionCount(session()));
3775 EXPECT_EQ(kProtoQUIC, request4->negotiated_protocol());
3776
3777 // Create another request that will alias and reuse the first session.
3778 std::unique_ptr<HttpStreamRequest> request5(
3779 session()->http_stream_factory()->RequestStream(
3780 request_info_b, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3781 &waiter2, /* enable_ip_based_pooling = */ true,
3782 /* enable_alternative_services = */ true, NetLogWithSource()));
3783 waiter2.WaitForStream();
3784 EXPECT_TRUE(waiter2.stream_done());
3785 EXPECT_FALSE(waiter2.websocket_stream());
3786 ASSERT_TRUE(waiter2.stream());
3787 EXPECT_EQ(kDnsAliasesB, waiter2.stream()->GetDnsAliases());
3788
3789 // Verify the session pool reused the first session and no new session is
3790 // created. This will fail unless the session pool supports multiple
3791 // sessions aliasing a single IP.
3792 EXPECT_EQ(1, GetQuicSessionCount(session()));
3793 EXPECT_EQ(kProtoQUIC, request5->negotiated_protocol());
3794
3795 // Create another request that will alias and reuse the first session.
3796 std::unique_ptr<HttpStreamRequest> request6(
3797 session()->http_stream_factory()->RequestStream(
3798 request_info_c, DEFAULT_PRIORITY, /* allowed_bad_certs = */ {},
3799 &waiter3, /* enable_ip_based_pooling = */ true,
3800 /* enable_alternative_services = */ true, NetLogWithSource()));
3801 waiter3.WaitForStream();
3802 EXPECT_TRUE(waiter3.stream_done());
3803 EXPECT_FALSE(waiter3.websocket_stream());
3804 ASSERT_TRUE(waiter3.stream());
3805 EXPECT_THAT(waiter3.stream()->GetDnsAliases(), ElementsAre(kUrlC.host()));
3806
3807 // Verify the session pool reused the first session and no new session is
3808 // created. This will fail unless the session pool supports multiple
3809 // sessions aliasing a single IP.
3810 EXPECT_EQ(1, GetQuicSessionCount(session()));
3811 EXPECT_EQ(kProtoQUIC, request6->negotiated_protocol());
3812 }
3813
3814 class ProcessAlternativeServicesTest : public TestWithTaskEnvironment {
3815 public:
ProcessAlternativeServicesTest()3816 ProcessAlternativeServicesTest() {
3817 session_params_.enable_quic = true;
3818
3819 session_context_.proxy_resolution_service = proxy_resolution_service_.get();
3820 session_context_.host_resolver = &host_resolver_;
3821 session_context_.cert_verifier = &cert_verifier_;
3822 session_context_.transport_security_state = &transport_security_state_;
3823 session_context_.client_socket_factory = &socket_factory_;
3824 session_context_.ssl_config_service = &ssl_config_service_;
3825 session_context_.http_server_properties = &http_server_properties_;
3826 session_context_.quic_context = &quic_context_;
3827 }
3828
3829 private:
3830 // Parameters passed in the NetworkSessionContext must outlive the
3831 // HttpNetworkSession.
3832 std::unique_ptr<ProxyResolutionService> proxy_resolution_service_ =
3833 ConfiguredProxyResolutionService::CreateDirect();
3834 SSLConfigServiceDefaults ssl_config_service_;
3835 MockClientSocketFactory socket_factory_;
3836 MockHostResolver host_resolver_;
3837 MockCertVerifier cert_verifier_;
3838 TransportSecurityState transport_security_state_;
3839
3840 protected:
3841 HttpServerProperties http_server_properties_;
3842 QuicContext quic_context_;
3843 HttpNetworkSessionParams session_params_;
3844 HttpNetworkSessionContext session_context_;
3845 std::unique_ptr<HttpNetworkSession> session_;
3846 };
3847
TEST_F(ProcessAlternativeServicesTest,ProcessEmptyAltSvc)3848 TEST_F(ProcessAlternativeServicesTest, ProcessEmptyAltSvc) {
3849 session_ =
3850 std::make_unique<HttpNetworkSession>(session_params_, session_context_);
3851 url::SchemeHostPort origin;
3852 NetworkAnonymizationKey network_anonymization_key;
3853
3854 auto headers = base::MakeRefCounted<HttpResponseHeaders>("");
3855
3856 session_->http_stream_factory()->ProcessAlternativeServices(
3857 session_.get(), network_anonymization_key, headers.get(), origin);
3858
3859 AlternativeServiceInfoVector alternatives =
3860 http_server_properties_.GetAlternativeServiceInfos(
3861 origin, network_anonymization_key);
3862 EXPECT_TRUE(alternatives.empty());
3863 }
3864
TEST_F(ProcessAlternativeServicesTest,ProcessAltSvcClear)3865 TEST_F(ProcessAlternativeServicesTest, ProcessAltSvcClear) {
3866 session_ =
3867 std::make_unique<HttpNetworkSession>(session_params_, session_context_);
3868 url::SchemeHostPort origin(url::kHttpsScheme, "example.com", 443);
3869
3870 auto network_anonymization_key = NetworkAnonymizationKey::CreateSameSite(
3871 SchemefulSite(GURL("https://example.com")));
3872
3873 http_server_properties_.SetAlternativeServices(
3874 origin, network_anonymization_key,
3875 {AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
3876 {kProtoQUIC, "", 443}, base::Time::Now() + base::Seconds(30),
3877 quic::AllSupportedVersions())});
3878
3879 EXPECT_FALSE(
3880 http_server_properties_
3881 .GetAlternativeServiceInfos(origin, network_anonymization_key)
3882 .empty());
3883
3884 auto headers = base::MakeRefCounted<HttpResponseHeaders>("");
3885 headers->AddHeader("alt-svc", "clear");
3886
3887 session_->http_stream_factory()->ProcessAlternativeServices(
3888 session_.get(), network_anonymization_key, headers.get(), origin);
3889
3890 AlternativeServiceInfoVector alternatives =
3891 http_server_properties_.GetAlternativeServiceInfos(
3892 origin, network_anonymization_key);
3893 EXPECT_TRUE(alternatives.empty());
3894 }
3895
TEST_F(ProcessAlternativeServicesTest,ProcessAltSvcQuicIetf)3896 TEST_F(ProcessAlternativeServicesTest, ProcessAltSvcQuicIetf) {
3897 quic_context_.params()->supported_versions = quic::AllSupportedVersions();
3898 session_ =
3899 std::make_unique<HttpNetworkSession>(session_params_, session_context_);
3900 url::SchemeHostPort origin(url::kHttpsScheme, "example.com", 443);
3901
3902 auto network_anonymization_key = NetworkAnonymizationKey::CreateSameSite(
3903 SchemefulSite(GURL("https://example.com")));
3904
3905 auto headers = base::MakeRefCounted<HttpResponseHeaders>("");
3906 headers->AddHeader("alt-svc",
3907 "h3-29=\":443\","
3908 "h3-Q050=\":443\","
3909 "h3-Q043=\":443\"");
3910
3911 session_->http_stream_factory()->ProcessAlternativeServices(
3912 session_.get(), network_anonymization_key, headers.get(), origin);
3913
3914 quic::ParsedQuicVersionVector versions = {
3915 quic::ParsedQuicVersion::Draft29(),
3916 };
3917 AlternativeServiceInfoVector alternatives =
3918 http_server_properties_.GetAlternativeServiceInfos(
3919 origin, network_anonymization_key);
3920 ASSERT_EQ(versions.size(), alternatives.size());
3921 for (size_t i = 0; i < alternatives.size(); ++i) {
3922 EXPECT_EQ(kProtoQUIC, alternatives[i].protocol());
3923 EXPECT_EQ(HostPortPair("example.com", 443),
3924 alternatives[i].host_port_pair());
3925 EXPECT_EQ(1u, alternatives[i].advertised_versions().size());
3926 EXPECT_EQ(versions[i], alternatives[i].advertised_versions()[0]);
3927 }
3928 }
3929
TEST_F(ProcessAlternativeServicesTest,ProcessAltSvcHttp2)3930 TEST_F(ProcessAlternativeServicesTest, ProcessAltSvcHttp2) {
3931 quic_context_.params()->supported_versions = quic::AllSupportedVersions();
3932 session_ =
3933 std::make_unique<HttpNetworkSession>(session_params_, session_context_);
3934 url::SchemeHostPort origin(url::kHttpsScheme, "example.com", 443);
3935
3936 auto network_anonymization_key = NetworkAnonymizationKey::CreateSameSite(
3937 SchemefulSite(GURL("https://example.com")));
3938
3939 auto headers = base::MakeRefCounted<HttpResponseHeaders>("");
3940 headers->AddHeader("alt-svc", "h2=\"other.example.com:443\"");
3941
3942 session_->http_stream_factory()->ProcessAlternativeServices(
3943 session_.get(), network_anonymization_key, headers.get(), origin);
3944
3945 AlternativeServiceInfoVector alternatives =
3946 http_server_properties_.GetAlternativeServiceInfos(
3947 origin, network_anonymization_key);
3948 ASSERT_EQ(1u, alternatives.size());
3949 EXPECT_EQ(kProtoHTTP2, alternatives[0].protocol());
3950 EXPECT_EQ(HostPortPair("other.example.com", 443),
3951 alternatives[0].host_port_pair());
3952 EXPECT_EQ(0u, alternatives[0].advertised_versions().size());
3953 }
3954
3955 } // namespace
3956
3957 } // namespace net::test
3958