• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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/spdy/spdy_session_pool.h"
6 
7 #include <cstddef>
8 #include <tuple>
9 #include <utility>
10 
11 #include "base/functional/bind.h"
12 #include "base/functional/callback.h"
13 #include "base/memory/raw_ptr.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/run_loop.h"
16 #include "base/test/bind.h"
17 #include "base/test/metrics/histogram_tester.h"
18 #include "base/trace_event/memory_allocator_dump.h"
19 #include "base/trace_event/process_memory_dump.h"
20 #include "build/build_config.h"
21 #include "net/base/proxy_string_util.h"
22 #include "net/base/test_completion_callback.h"
23 #include "net/base/tracing.h"
24 #include "net/dns/host_cache.h"
25 #include "net/dns/public/host_resolver_results.h"
26 #include "net/dns/public/secure_dns_policy.h"
27 #include "net/http/http_network_session.h"
28 #include "net/log/net_log_with_source.h"
29 #include "net/log/test_net_log.h"
30 #include "net/socket/client_socket_handle.h"
31 #include "net/socket/socket_tag.h"
32 #include "net/socket/socket_test_util.h"
33 #include "net/socket/transport_client_socket_pool.h"
34 #include "net/spdy/spdy_session.h"
35 #include "net/spdy/spdy_stream_test_util.h"
36 #include "net/spdy/spdy_test_util_common.h"
37 #include "net/test/cert_test_util.h"
38 #include "net/test/gtest_util.h"
39 #include "net/test/test_certificate_data.h"
40 #include "net/test/test_data_directory.h"
41 #include "net/test/test_with_task_environment.h"
42 #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
43 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
44 #include "testing/gmock/include/gmock/gmock.h"
45 #include "testing/gtest/include/gtest/gtest.h"
46 
47 using base::trace_event::MemoryAllocatorDump;
48 using net::test::IsError;
49 using net::test::IsOk;
50 using testing::Contains;
51 using testing::Eq;
52 using testing::Contains;
53 using testing::ByRef;
54 
55 namespace net {
56 
57 class SpdySessionPoolTest : public TestWithTaskEnvironment {
58  protected:
59   // Used by RunIPPoolingTest().
60   enum SpdyPoolCloseSessionsType {
61     SPDY_POOL_CLOSE_SESSIONS_MANUALLY,
62     SPDY_POOL_CLOSE_CURRENT_SESSIONS,
63     SPDY_POOL_CLOSE_IDLE_SESSIONS,
64   };
65 
66   SpdySessionPoolTest() = default;
67 
CreateNetworkSession()68   void CreateNetworkSession() {
69     http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
70     spdy_session_pool_ = http_session_->spdy_session_pool();
71   }
72 
AddSSLSocketData()73   void AddSSLSocketData() {
74     auto ssl = std::make_unique<SSLSocketDataProvider>(SYNCHRONOUS, OK);
75     ssl->ssl_info.cert =
76         ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
77     ASSERT_TRUE(ssl->ssl_info.cert);
78     session_deps_.socket_factory->AddSSLSocketDataProvider(ssl.get());
79     ssl_data_vector_.push_back(std::move(ssl));
80   }
81 
82   void RunIPPoolingTest(SpdyPoolCloseSessionsType close_sessions_type);
83   void RunIPPoolingDisabledTest(SSLSocketDataProvider* ssl);
84 
num_active_streams(base::WeakPtr<SpdySession> session)85   size_t num_active_streams(base::WeakPtr<SpdySession> session) {
86     return session->active_streams_.size();
87   }
88 
max_concurrent_streams(base::WeakPtr<SpdySession> session)89   size_t max_concurrent_streams(base::WeakPtr<SpdySession> session) {
90     return session->max_concurrent_streams_;
91   }
92 
93   SpdySessionDependencies session_deps_;
94   std::unique_ptr<HttpNetworkSession> http_session_;
95   raw_ptr<SpdySessionPool, DanglingUntriaged> spdy_session_pool_ = nullptr;
96   std::vector<std::unique_ptr<SSLSocketDataProvider>> ssl_data_vector_;
97 };
98 
99 class SpdySessionRequestDelegate
100     : public SpdySessionPool::SpdySessionRequest::Delegate {
101  public:
102   SpdySessionRequestDelegate() = default;
103 
104   SpdySessionRequestDelegate(const SpdySessionRequestDelegate&) = delete;
105   SpdySessionRequestDelegate& operator=(const SpdySessionRequestDelegate&) =
106       delete;
107 
108   ~SpdySessionRequestDelegate() override = default;
109 
OnSpdySessionAvailable(base::WeakPtr<SpdySession> spdy_session)110   void OnSpdySessionAvailable(
111       base::WeakPtr<SpdySession> spdy_session) override {
112     EXPECT_FALSE(callback_invoked_);
113     callback_invoked_ = true;
114     spdy_session_ = spdy_session;
115   }
116 
callback_invoked() const117   bool callback_invoked() const { return callback_invoked_; }
118 
spdy_session()119   SpdySession* spdy_session() { return spdy_session_.get(); }
120 
121  private:
122   bool callback_invoked_ = false;
123   base::WeakPtr<SpdySession> spdy_session_;
124 };
125 
126 // Attempts to set up an alias for |key| using an already existing session in
127 // |pool|. To do this, simulates a host resolution that returns
128 // |endpoints|.
TryCreateAliasedSpdySession(SpdySessionPool * pool,const SpdySessionKey & key,const std::vector<HostResolverEndpointResult> & endpoints,bool enable_ip_based_pooling=true,bool is_websocket=false)129 bool TryCreateAliasedSpdySession(
130     SpdySessionPool* pool,
131     const SpdySessionKey& key,
132     const std::vector<HostResolverEndpointResult>& endpoints,
133     bool enable_ip_based_pooling = true,
134     bool is_websocket = false) {
135   // The requested session must not already exist.
136   EXPECT_FALSE(pool->FindAvailableSession(key, enable_ip_based_pooling,
137                                           is_websocket, NetLogWithSource()));
138 
139   // Create a request for the session. There should be no matching session
140   // (aliased or otherwise) yet. A pending request is necessary for the session
141   // to create an alias on host resolution completion.
142   std::unique_ptr<SpdySessionPool::SpdySessionRequest> request;
143   bool is_blocking_request_for_session = false;
144   SpdySessionRequestDelegate request_delegate;
145   EXPECT_FALSE(pool->RequestSession(
146       key, enable_ip_based_pooling, is_websocket, NetLogWithSource(),
147       /* on_blocking_request_destroyed_callback = */ base::RepeatingClosure(),
148       &request_delegate, &request, &is_blocking_request_for_session));
149   EXPECT_TRUE(request);
150   EXPECT_TRUE(is_blocking_request_for_session);
151 
152   // Simulate a host resolution completing.
153   OnHostResolutionCallbackResult result = pool->OnHostResolutionComplete(
154       key, is_websocket, endpoints, /*aliases=*/{});
155 
156   // Spin the message loop and see if it creates an H2 session.
157   base::RunLoop().RunUntilIdle();
158   EXPECT_EQ(request_delegate.callback_invoked(),
159             result == OnHostResolutionCallbackResult::kMayBeDeletedAsync);
160   EXPECT_EQ(request_delegate.callback_invoked(),
161             request_delegate.spdy_session() != nullptr);
162   request.reset();
163 
164   // Calling RequestSession again should return request_delegate.spdy_session()
165   // (i.e. the newly created session, if a session was created, or nullptr, if
166   // one was not.)
167   EXPECT_EQ(request_delegate.spdy_session(),
168             pool->RequestSession(key, enable_ip_based_pooling, is_websocket,
169                                  NetLogWithSource(),
170                                  /* on_blocking_request_destroyed_callback = */
171                                  base::RepeatingClosure(), &request_delegate,
172                                  &request, &is_blocking_request_for_session)
173                 .get());
174 
175   return request_delegate.spdy_session() != nullptr;
176 }
177 
178 // Attempts to set up an alias for |key| using an already existing session in
179 // |pool|. To do this, simulates a host resolution that returns
180 // |ip_address_list|.
TryCreateAliasedSpdySession(SpdySessionPool * pool,const SpdySessionKey & key,const std::string & ip_address_list,bool enable_ip_based_pooling=true,bool is_websocket=false)181 bool TryCreateAliasedSpdySession(SpdySessionPool* pool,
182                                  const SpdySessionKey& key,
183                                  const std::string& ip_address_list,
184                                  bool enable_ip_based_pooling = true,
185                                  bool is_websocket = false) {
186   std::vector<IPEndPoint> ip_endpoints;
187   EXPECT_THAT(ParseAddressList(ip_address_list, &ip_endpoints), IsOk());
188   HostResolverEndpointResult endpoint;
189   for (auto& ip_endpoint : ip_endpoints) {
190     endpoint.ip_endpoints.emplace_back(ip_endpoint.address(), 443);
191   }
192   return TryCreateAliasedSpdySession(pool, key, {endpoint},
193                                      enable_ip_based_pooling, is_websocket);
194 }
195 
196 // A delegate that opens a new session when it is closed.
197 class SessionOpeningDelegate : public SpdyStream::Delegate {
198  public:
SessionOpeningDelegate(SpdySessionPool * spdy_session_pool,const SpdySessionKey & key)199   SessionOpeningDelegate(SpdySessionPool* spdy_session_pool,
200                          const SpdySessionKey& key)
201       : spdy_session_pool_(spdy_session_pool),
202         key_(key) {}
203 
204   ~SessionOpeningDelegate() override = default;
205 
OnHeadersSent()206   void OnHeadersSent() override {}
207 
OnEarlyHintsReceived(const spdy::Http2HeaderBlock & headers)208   void OnEarlyHintsReceived(const spdy::Http2HeaderBlock& headers) override {}
209 
OnHeadersReceived(const spdy::Http2HeaderBlock & response_headers)210   void OnHeadersReceived(
211       const spdy::Http2HeaderBlock& response_headers) override {}
212 
OnDataReceived(std::unique_ptr<SpdyBuffer> buffer)213   void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) override {}
214 
OnDataSent()215   void OnDataSent() override {}
216 
OnTrailers(const spdy::Http2HeaderBlock & trailers)217   void OnTrailers(const spdy::Http2HeaderBlock& trailers) override {}
218 
OnClose(int status)219   void OnClose(int status) override {
220     std::ignore = CreateFakeSpdySession(spdy_session_pool_, key_);
221   }
222 
CanGreaseFrameType() const223   bool CanGreaseFrameType() const override { return false; }
224 
source_dependency() const225   NetLogSource source_dependency() const override { return NetLogSource(); }
226 
227  private:
228   const raw_ptr<SpdySessionPool> spdy_session_pool_;
229   const SpdySessionKey key_;
230 };
231 
232 // Set up a SpdyStream to create a new session when it is closed.
233 // CloseCurrentSessions should not close the newly-created session.
TEST_F(SpdySessionPoolTest,CloseCurrentSessions)234 TEST_F(SpdySessionPoolTest, CloseCurrentSessions) {
235   const char kTestHost[] = "www.foo.com";
236   const int kTestPort = 80;
237 
238   HostPortPair test_host_port_pair(kTestHost, kTestPort);
239   SpdySessionKey test_key = SpdySessionKey(
240       test_host_port_pair, ProxyChain::Direct(), PRIVACY_MODE_DISABLED,
241       SpdySessionKey::IsProxySession::kFalse, SocketTag(),
242       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
243 
244   MockConnect connect_data(SYNCHRONOUS, OK);
245   MockRead reads[] = {
246     MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
247   };
248 
249   StaticSocketDataProvider data(reads, base::span<MockWrite>());
250   data.set_connect_data(connect_data);
251   session_deps_.socket_factory->AddSocketDataProvider(&data);
252 
253   SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
254   session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
255 
256   CreateNetworkSession();
257 
258   // Setup the first session to the first host.
259   base::WeakPtr<SpdySession> session =
260       CreateSpdySession(http_session_.get(), test_key, NetLogWithSource());
261 
262   // Flush the SpdySession::OnReadComplete() task.
263   base::RunLoop().RunUntilIdle();
264 
265   // Verify that we have sessions for everything.
266   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
267 
268   // Set the stream to create a new session when it is closed.
269   base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
270       SPDY_BIDIRECTIONAL_STREAM, session, GURL("http://www.foo.com"), MEDIUM,
271       NetLogWithSource());
272   SessionOpeningDelegate delegate(spdy_session_pool_, test_key);
273   spdy_stream->SetDelegate(&delegate);
274 
275   // Close the current session.
276   spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED);
277 
278   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
279 }
280 
TEST_F(SpdySessionPoolTest,CloseCurrentIdleSessions)281 TEST_F(SpdySessionPoolTest, CloseCurrentIdleSessions) {
282   const std::string close_session_description = "Closing idle sessions.";
283   MockConnect connect_data(SYNCHRONOUS, OK);
284   MockRead reads[] = {
285       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
286   };
287 
288   StaticSocketDataProvider data1(reads, base::span<MockWrite>());
289   data1.set_connect_data(connect_data);
290   session_deps_.socket_factory->AddSocketDataProvider(&data1);
291 
292   AddSSLSocketData();
293   AddSSLSocketData();
294   AddSSLSocketData();
295 
296   CreateNetworkSession();
297 
298   // Set up session 1
299   const GURL url1("https://www.example.org");
300   HostPortPair test_host_port_pair1(HostPortPair::FromURL(url1));
301   SpdySessionKey key1(test_host_port_pair1, ProxyChain::Direct(),
302                       PRIVACY_MODE_DISABLED,
303                       SpdySessionKey::IsProxySession::kFalse, SocketTag(),
304                       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
305   base::WeakPtr<SpdySession> session1 =
306       CreateSpdySession(http_session_.get(), key1, NetLogWithSource());
307   base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(
308       SPDY_BIDIRECTIONAL_STREAM, session1, url1, MEDIUM, NetLogWithSource());
309   ASSERT_TRUE(spdy_stream1);
310 
311   // Set up session 2
312   StaticSocketDataProvider data2(reads, base::span<MockWrite>());
313   session_deps_.socket_factory->AddSocketDataProvider(&data2);
314   const GURL url2("https://mail.example.org");
315   HostPortPair test_host_port_pair2(HostPortPair::FromURL(url2));
316   SpdySessionKey key2(test_host_port_pair2, ProxyChain::Direct(),
317                       PRIVACY_MODE_DISABLED,
318                       SpdySessionKey::IsProxySession::kFalse, SocketTag(),
319                       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
320   base::WeakPtr<SpdySession> session2 =
321       CreateSpdySession(http_session_.get(), key2, NetLogWithSource());
322   base::WeakPtr<SpdyStream> spdy_stream2 = CreateStreamSynchronously(
323       SPDY_BIDIRECTIONAL_STREAM, session2, url2, MEDIUM, NetLogWithSource());
324   ASSERT_TRUE(spdy_stream2);
325 
326   // Set up session 3
327   StaticSocketDataProvider data3(reads, base::span<MockWrite>());
328   data3.set_connect_data(connect_data);
329   session_deps_.socket_factory->AddSocketDataProvider(&data3);
330   const GURL url3("https://mail.example.com");
331   HostPortPair test_host_port_pair3(HostPortPair::FromURL(url3));
332   SpdySessionKey key3(test_host_port_pair3, ProxyChain::Direct(),
333                       PRIVACY_MODE_DISABLED,
334                       SpdySessionKey::IsProxySession::kFalse, SocketTag(),
335                       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
336   base::WeakPtr<SpdySession> session3 =
337       CreateSpdySession(http_session_.get(), key3, NetLogWithSource());
338   base::WeakPtr<SpdyStream> spdy_stream3 = CreateStreamSynchronously(
339       SPDY_BIDIRECTIONAL_STREAM, session3, url3, MEDIUM, NetLogWithSource());
340   ASSERT_TRUE(spdy_stream3);
341 
342   // All sessions are active and not closed
343   EXPECT_TRUE(session1->is_active());
344   EXPECT_TRUE(session1->IsAvailable());
345   EXPECT_TRUE(session2->is_active());
346   EXPECT_TRUE(session2->IsAvailable());
347   EXPECT_TRUE(session3->is_active());
348   EXPECT_TRUE(session3->IsAvailable());
349 
350   // Should not do anything, all are active
351   spdy_session_pool_->CloseCurrentIdleSessions(close_session_description);
352   EXPECT_TRUE(session1->is_active());
353   EXPECT_TRUE(session1->IsAvailable());
354   EXPECT_TRUE(session2->is_active());
355   EXPECT_TRUE(session2->IsAvailable());
356   EXPECT_TRUE(session3->is_active());
357   EXPECT_TRUE(session3->IsAvailable());
358 
359   // Make sessions 1 and 3 inactive, but keep them open.
360   // Session 2 still open and active
361   session1->CloseCreatedStream(spdy_stream1, OK);
362   EXPECT_FALSE(spdy_stream1);
363   session3->CloseCreatedStream(spdy_stream3, OK);
364   EXPECT_FALSE(spdy_stream3);
365   EXPECT_FALSE(session1->is_active());
366   EXPECT_TRUE(session1->IsAvailable());
367   EXPECT_TRUE(session2->is_active());
368   EXPECT_TRUE(session2->IsAvailable());
369   EXPECT_FALSE(session3->is_active());
370   EXPECT_TRUE(session3->IsAvailable());
371 
372   // Should close session 1 and 3, 2 should be left open
373   spdy_session_pool_->CloseCurrentIdleSessions(close_session_description);
374   base::RunLoop().RunUntilIdle();
375 
376   EXPECT_FALSE(session1);
377   EXPECT_TRUE(session2->is_active());
378   EXPECT_TRUE(session2->IsAvailable());
379   EXPECT_FALSE(session3);
380 
381   // Should not do anything
382   spdy_session_pool_->CloseCurrentIdleSessions(close_session_description);
383   base::RunLoop().RunUntilIdle();
384 
385   EXPECT_TRUE(session2->is_active());
386   EXPECT_TRUE(session2->IsAvailable());
387 
388   // Make 2 not active
389   session2->CloseCreatedStream(spdy_stream2, OK);
390   base::RunLoop().RunUntilIdle();
391 
392   EXPECT_FALSE(spdy_stream2);
393   EXPECT_FALSE(session2->is_active());
394   EXPECT_TRUE(session2->IsAvailable());
395 
396   // This should close session 2
397   spdy_session_pool_->CloseCurrentIdleSessions(close_session_description);
398   base::RunLoop().RunUntilIdle();
399 
400   EXPECT_FALSE(session2);
401 }
402 
403 // Set up a SpdyStream to create a new session when it is closed.
404 // CloseAllSessions should close the newly-created session.
TEST_F(SpdySessionPoolTest,CloseAllSessions)405 TEST_F(SpdySessionPoolTest, CloseAllSessions) {
406   const char kTestHost[] = "www.foo.com";
407   const int kTestPort = 80;
408 
409   HostPortPair test_host_port_pair(kTestHost, kTestPort);
410   SpdySessionKey test_key = SpdySessionKey(
411       test_host_port_pair, ProxyChain::Direct(), PRIVACY_MODE_DISABLED,
412       SpdySessionKey::IsProxySession::kFalse, SocketTag(),
413       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
414 
415   MockConnect connect_data(SYNCHRONOUS, OK);
416   MockRead reads[] = {
417     MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
418   };
419 
420   StaticSocketDataProvider data(reads, base::span<MockWrite>());
421   data.set_connect_data(connect_data);
422   session_deps_.socket_factory->AddSocketDataProvider(&data);
423 
424   SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
425   session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
426 
427   CreateNetworkSession();
428 
429   // Setup the first session to the first host.
430   base::WeakPtr<SpdySession> session =
431       CreateSpdySession(http_session_.get(), test_key, NetLogWithSource());
432 
433   // Flush the SpdySession::OnReadComplete() task.
434   base::RunLoop().RunUntilIdle();
435 
436   // Verify that we have sessions for everything.
437   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
438 
439   // Set the stream to create a new session when it is closed.
440   base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
441       SPDY_BIDIRECTIONAL_STREAM, session, GURL("http://www.foo.com"), MEDIUM,
442       NetLogWithSource());
443   SessionOpeningDelegate delegate(spdy_session_pool_, test_key);
444   spdy_stream->SetDelegate(&delegate);
445 
446   // Close the current session.
447   spdy_session_pool_->CloseAllSessions();
448 
449   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_key));
450 }
451 
452 // Code testing SpdySessionPool::OnIPAddressChange requires a SpdySessionPool
453 // with some active sessions. This fixture takes care of setting most things up
454 // but doesn't create the pool yet, allowing tests to possibly further
455 // configure sessions_deps_.
456 class SpdySessionPoolOnIPAddressChangeTest : public SpdySessionPoolTest {
457  protected:
SpdySessionPoolOnIPAddressChangeTest()458   SpdySessionPoolOnIPAddressChangeTest()
459       : test_host_port_pair_(kTestHost, kTestPort),
460         reads_({
461             MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
462         }),
463         test_key_(SpdySessionKey(test_host_port_pair_,
464                                  ProxyChain::Direct(),
465                                  PRIVACY_MODE_DISABLED,
466                                  SpdySessionKey::IsProxySession::kFalse,
467                                  SocketTag(),
468                                  NetworkAnonymizationKey(),
469                                  SecureDnsPolicy::kAllow)),
470         connect_data_(SYNCHRONOUS, OK),
471         data_(reads_, base::span<MockWrite>()),
472         ssl_(SYNCHRONOUS, OK) {
473     data_.set_connect_data(connect_data_);
474     session_deps_.socket_factory->AddSocketDataProvider(&data_);
475     session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
476   }
477 
478   static constexpr char kTestHost[] = "www.foo.com";
479   static constexpr int kTestPort = 80;
480   static constexpr int kReadSize = 1;
481 
482   const HostPortPair test_host_port_pair_;
483   const std::array<MockRead, kReadSize> reads_;
484   const SpdySessionKey test_key_;
485   const MockConnect connect_data_;
486   StaticSocketDataProvider data_;
487   SSLSocketDataProvider ssl_;
488 };
489 
TEST_F(SpdySessionPoolOnIPAddressChangeTest,DoNotIgnoreIPAddressChanges)490 TEST_F(SpdySessionPoolOnIPAddressChangeTest, DoNotIgnoreIPAddressChanges) {
491   // Default behavior should be ignore_ip_address_changes = false;
492   CreateNetworkSession();
493 
494   base::WeakPtr<SpdySession> session =
495       CreateSpdySession(http_session_.get(), test_key_, NetLogWithSource());
496 
497   // Flush the SpdySession::OnReadComplete() task.
498   base::RunLoop().RunUntilIdle();
499   // Verify that we have a session.
500   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key_));
501 
502   // Without setting session_deps_.ignore_ip_address_changes = true the pool
503   // should close (or make unavailable) all sessions after an IP address change.
504   NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
505   base::RunLoop().RunUntilIdle();
506   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_key_));
507 }
508 
TEST_F(SpdySessionPoolOnIPAddressChangeTest,IgnoreIPAddressChanges)509 TEST_F(SpdySessionPoolOnIPAddressChangeTest, IgnoreIPAddressChanges) {
510   session_deps_.ignore_ip_address_changes = true;
511   CreateNetworkSession();
512 
513   // Setup the first session to the first host.
514   base::WeakPtr<SpdySession> session =
515       CreateSpdySession(http_session_.get(), test_key_, NetLogWithSource());
516   // Flush the SpdySession::OnReadComplete() task.
517   base::RunLoop().RunUntilIdle();
518   // Verify that we have a session.
519   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key_));
520 
521   // Since we set ignore_ip_address_changes = true, the session should still be
522   // there after an IP address change.
523   NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
524   base::RunLoop().RunUntilIdle();
525   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key_));
526 }
527 
528 // This test has three variants, one for each style of closing the connection.
529 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_SESSIONS_MANUALLY,
530 // the sessions are closed manually, calling SpdySessionPool::Remove() directly.
531 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_CURRENT_SESSIONS,
532 // sessions are closed with SpdySessionPool::CloseCurrentSessions().
533 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_IDLE_SESSIONS,
534 // sessions are closed with SpdySessionPool::CloseIdleSessions().
RunIPPoolingTest(SpdyPoolCloseSessionsType close_sessions_type)535 void SpdySessionPoolTest::RunIPPoolingTest(
536     SpdyPoolCloseSessionsType close_sessions_type) {
537   constexpr int kTestPort = 443;
538   struct TestHosts {
539     std::string url;
540     std::string name;
541     std::string iplist;
542     SpdySessionKey key;
543   } test_hosts[] = {
544       {"http://www.example.org", "www.example.org",
545        "192.0.2.33,192.168.0.1,192.168.0.5"},
546       {"http://mail.example.org", "mail.example.org",
547        "192.168.0.2,192.168.0.3,192.168.0.5,192.0.2.33"},
548       {"http://mail.example.com", "mail.example.com",
549        "192.168.0.4,192.168.0.3"},
550   };
551 
552   for (auto& test_host : test_hosts) {
553     session_deps_.host_resolver->rules()->AddIPLiteralRule(
554         test_host.name, test_host.iplist, std::string());
555 
556     test_host.key = SpdySessionKey(
557         HostPortPair(test_host.name, kTestPort), ProxyChain::Direct(),
558         PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
559         SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
560   }
561 
562   MockConnect connect_data(SYNCHRONOUS, OK);
563   MockRead reads[] = {
564     MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
565   };
566 
567   StaticSocketDataProvider data1(reads, base::span<MockWrite>());
568   data1.set_connect_data(connect_data);
569   session_deps_.socket_factory->AddSocketDataProvider(&data1);
570 
571   AddSSLSocketData();
572 
573   CreateNetworkSession();
574 
575   // Setup the first session to the first host.
576   base::WeakPtr<SpdySession> session = CreateSpdySession(
577       http_session_.get(), test_hosts[0].key, NetLogWithSource());
578 
579   // Flush the SpdySession::OnReadComplete() task.
580   base::RunLoop().RunUntilIdle();
581 
582   // The third host has no overlap with the first, so it can't pool IPs.
583   EXPECT_FALSE(TryCreateAliasedSpdySession(
584       spdy_session_pool_, test_hosts[2].key, test_hosts[2].iplist));
585 
586   // The second host overlaps with the first, and should IP pool.
587   EXPECT_TRUE(TryCreateAliasedSpdySession(spdy_session_pool_, test_hosts[1].key,
588                                           test_hosts[1].iplist));
589 
590   // However, if IP pooling is disabled, FindAvailableSession() should not find
591   // |session| for the second host.
592   base::WeakPtr<SpdySession> session1 =
593       spdy_session_pool_->FindAvailableSession(
594           test_hosts[1].key, /* enable_ip_based_pooling = */ false,
595           /* is_websocket = */ false, NetLogWithSource());
596   EXPECT_FALSE(session1);
597 
598   // Verify that the second host, through a proxy, won't share the IP, even if
599   // the IP list matches.
600   SpdySessionKey proxy_key(
601       test_hosts[1].key.host_port_pair(),
602       PacResultElementToProxyChain("HTTP http://proxy.foo.com/"),
603       PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
604       SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
605   EXPECT_FALSE(TryCreateAliasedSpdySession(spdy_session_pool_, proxy_key,
606                                            test_hosts[1].iplist));
607 
608   // Verify that the second host, with a different SecureDnsPolicy,
609   // won't share the IP, even if the IP list matches.
610   SpdySessionKey disable_secure_dns_key(
611       test_hosts[1].key.host_port_pair(), ProxyChain::Direct(),
612       PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
613       SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kDisable);
614   EXPECT_FALSE(TryCreateAliasedSpdySession(
615       spdy_session_pool_, disable_secure_dns_key, test_hosts[1].iplist));
616 
617   // Overlap between 2 and 3 is not transitive to 1.
618   EXPECT_FALSE(TryCreateAliasedSpdySession(
619       spdy_session_pool_, test_hosts[2].key, test_hosts[2].iplist));
620 
621   // Create a new session to host 2.
622   StaticSocketDataProvider data2(reads, base::span<MockWrite>());
623   data2.set_connect_data(connect_data);
624   session_deps_.socket_factory->AddSocketDataProvider(&data2);
625 
626   AddSSLSocketData();
627 
628   base::WeakPtr<SpdySession> session2 = CreateSpdySession(
629       http_session_.get(), test_hosts[2].key, NetLogWithSource());
630 
631   // Verify that we have sessions for everything.
632   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[0].key));
633   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
634   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
635 
636   // Grab the session to host 1 and verify that it is the same session
637   // we got with host 0, and that is a different from host 2's session.
638   session1 = spdy_session_pool_->FindAvailableSession(
639       test_hosts[1].key, /* enable_ip_based_pooling = */ true,
640       /* is_websocket = */ false, NetLogWithSource());
641   EXPECT_EQ(session.get(), session1.get());
642   EXPECT_NE(session2.get(), session1.get());
643 
644   // Remove the aliases and observe that we still have a session for host1.
645   SpdySessionPoolPeer pool_peer(spdy_session_pool_);
646   pool_peer.RemoveAliases(test_hosts[0].key);
647   pool_peer.RemoveAliases(test_hosts[1].key);
648   EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
649 
650   // Cleanup the sessions.
651   switch (close_sessions_type) {
652     case SPDY_POOL_CLOSE_SESSIONS_MANUALLY:
653       session->CloseSessionOnError(ERR_ABORTED, std::string());
654       session2->CloseSessionOnError(ERR_ABORTED, std::string());
655       base::RunLoop().RunUntilIdle();
656       EXPECT_FALSE(session);
657       EXPECT_FALSE(session2);
658       break;
659     case SPDY_POOL_CLOSE_CURRENT_SESSIONS:
660       spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED);
661       break;
662     case SPDY_POOL_CLOSE_IDLE_SESSIONS:
663       GURL url(test_hosts[0].url);
664       base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
665           SPDY_BIDIRECTIONAL_STREAM, session, url, MEDIUM, NetLogWithSource());
666       GURL url1(test_hosts[1].url);
667       base::WeakPtr<SpdyStream> spdy_stream1 =
668           CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session1, url1,
669                                     MEDIUM, NetLogWithSource());
670       GURL url2(test_hosts[2].url);
671       base::WeakPtr<SpdyStream> spdy_stream2 =
672           CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session2, url2,
673                                     MEDIUM, NetLogWithSource());
674 
675       // Close streams to make spdy_session and spdy_session1 inactive.
676       session->CloseCreatedStream(spdy_stream, OK);
677       EXPECT_FALSE(spdy_stream);
678       session1->CloseCreatedStream(spdy_stream1, OK);
679       EXPECT_FALSE(spdy_stream1);
680 
681       // Check spdy_session and spdy_session1 are not closed.
682       EXPECT_FALSE(session->is_active());
683       EXPECT_TRUE(session->IsAvailable());
684       EXPECT_FALSE(session1->is_active());
685       EXPECT_TRUE(session1->IsAvailable());
686       EXPECT_TRUE(session2->is_active());
687       EXPECT_TRUE(session2->IsAvailable());
688 
689       // Test that calling CloseIdleSessions, does not cause a crash.
690       // http://crbug.com/181400
691       spdy_session_pool_->CloseCurrentIdleSessions("Closing idle sessions.");
692       base::RunLoop().RunUntilIdle();
693 
694       // Verify spdy_session and spdy_session1 are closed.
695       EXPECT_FALSE(session);
696       EXPECT_FALSE(session1);
697       EXPECT_TRUE(session2->is_active());
698       EXPECT_TRUE(session2->IsAvailable());
699 
700       spdy_stream2->Cancel(ERR_ABORTED);
701       EXPECT_FALSE(spdy_stream);
702       EXPECT_FALSE(spdy_stream1);
703       EXPECT_FALSE(spdy_stream2);
704 
705       session2->CloseSessionOnError(ERR_ABORTED, std::string());
706       base::RunLoop().RunUntilIdle();
707       EXPECT_FALSE(session2);
708       break;
709   }
710 
711   // Verify that the map is all cleaned up.
712   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[0].key));
713   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
714   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
715   EXPECT_FALSE(TryCreateAliasedSpdySession(
716       spdy_session_pool_, test_hosts[0].key, test_hosts[0].iplist));
717   EXPECT_FALSE(TryCreateAliasedSpdySession(
718       spdy_session_pool_, test_hosts[1].key, test_hosts[1].iplist));
719   EXPECT_FALSE(TryCreateAliasedSpdySession(
720       spdy_session_pool_, test_hosts[2].key, test_hosts[2].iplist));
721 }
722 
RunIPPoolingDisabledTest(SSLSocketDataProvider * ssl)723 void SpdySessionPoolTest::RunIPPoolingDisabledTest(SSLSocketDataProvider* ssl) {
724   constexpr int kTestPort = 443;
725   struct TestHosts {
726     std::string name;
727     std::string iplist;
728     SpdySessionKey key;
729   } test_hosts[] = {
730       {"www.webkit.org", "192.0.2.33,192.168.0.1,192.168.0.5"},
731       {"js.webkit.com", "192.168.0.4,192.168.0.1,192.0.2.33"},
732   };
733 
734   session_deps_.host_resolver->set_synchronous_mode(true);
735   for (auto& test_host : test_hosts) {
736     session_deps_.host_resolver->rules()->AddIPLiteralRule(
737         test_host.name, test_host.iplist, std::string());
738 
739     // Setup a SpdySessionKey
740     test_host.key = SpdySessionKey(
741         HostPortPair(test_host.name, kTestPort), ProxyChain::Direct(),
742         PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
743         SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
744   }
745 
746   MockRead reads[] = {
747       MockRead(ASYNC, ERR_IO_PENDING),
748   };
749   StaticSocketDataProvider data(reads, base::span<MockWrite>());
750   session_deps_.socket_factory->AddSocketDataProvider(&data);
751   session_deps_.socket_factory->AddSSLSocketDataProvider(ssl);
752 
753   CreateNetworkSession();
754 
755   base::WeakPtr<SpdySession> spdy_session = CreateSpdySession(
756       http_session_.get(), test_hosts[0].key, NetLogWithSource());
757   EXPECT_TRUE(
758       HasSpdySession(http_session_->spdy_session_pool(), test_hosts[0].key));
759   EXPECT_FALSE(TryCreateAliasedSpdySession(
760       spdy_session_pool_, test_hosts[1].key, test_hosts[1].iplist,
761       /* enable_ip_based_pooling = */ false));
762 
763   http_session_->spdy_session_pool()->CloseAllSessions();
764 }
765 
TEST_F(SpdySessionPoolTest,IPPooling)766 TEST_F(SpdySessionPoolTest, IPPooling) {
767   RunIPPoolingTest(SPDY_POOL_CLOSE_SESSIONS_MANUALLY);
768 }
769 
TEST_F(SpdySessionPoolTest,IPPoolingCloseCurrentSessions)770 TEST_F(SpdySessionPoolTest, IPPoolingCloseCurrentSessions) {
771   RunIPPoolingTest(SPDY_POOL_CLOSE_CURRENT_SESSIONS);
772 }
773 
TEST_F(SpdySessionPoolTest,IPPoolingCloseIdleSessions)774 TEST_F(SpdySessionPoolTest, IPPoolingCloseIdleSessions) {
775   RunIPPoolingTest(SPDY_POOL_CLOSE_IDLE_SESSIONS);
776 }
777 
778 // Regression test for https://crbug.com/643025.
TEST_F(SpdySessionPoolTest,IPPoolingNetLog)779 TEST_F(SpdySessionPoolTest, IPPoolingNetLog) {
780   // Define two hosts with identical IP address.
781   constexpr int kTestPort = 443;
782   struct TestHosts {
783     std::string name;
784     std::string iplist;
785     SpdySessionKey key;
786   } test_hosts[] = {
787       {"www.example.org", "192.168.0.1"}, {"mail.example.org", "192.168.0.1"},
788   };
789 
790   // Populate the HostResolver cache.
791   session_deps_.host_resolver->set_synchronous_mode(true);
792   for (auto& test_host : test_hosts) {
793     session_deps_.host_resolver->rules()->AddIPLiteralRule(
794         test_host.name, test_host.iplist, std::string());
795 
796     test_host.key = SpdySessionKey(
797         HostPortPair(test_host.name, kTestPort), ProxyChain::Direct(),
798         PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
799         SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
800   }
801 
802   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
803   StaticSocketDataProvider data(reads, base::span<MockWrite>());
804   MockConnect connect_data(SYNCHRONOUS, OK);
805   data.set_connect_data(connect_data);
806 
807   session_deps_.socket_factory->AddSocketDataProvider(&data);
808   AddSSLSocketData();
809 
810   CreateNetworkSession();
811 
812   // Open SpdySession to the first host.
813   base::WeakPtr<SpdySession> session0 = CreateSpdySession(
814       http_session_.get(), test_hosts[0].key, NetLogWithSource());
815 
816   // The second host should pool to the existing connection.
817   RecordingNetLogObserver net_log_observer;
818   base::HistogramTester histogram_tester;
819   EXPECT_TRUE(TryCreateAliasedSpdySession(spdy_session_pool_, test_hosts[1].key,
820                                           test_hosts[1].iplist));
821   histogram_tester.ExpectTotalCount("Net.SpdySessionGet", 1);
822 
823   base::WeakPtr<SpdySession> session1 =
824       spdy_session_pool_->FindAvailableSession(
825           test_hosts[1].key, /* enable_ip_based_pooling = */ true,
826           /* is_websocket = */ false,
827           NetLogWithSource::Make(NetLogSourceType::NONE));
828   EXPECT_EQ(session0.get(), session1.get());
829 
830   ASSERT_EQ(1u, net_log_observer.GetSize());
831   histogram_tester.ExpectTotalCount("Net.SpdySessionGet", 2);
832 
833   // FindAvailableSession() should have logged a netlog event indicating IP
834   // pooling.
835   auto entry_list = net_log_observer.GetEntries();
836   EXPECT_EQ(
837       NetLogEventType::HTTP2_SESSION_POOL_FOUND_EXISTING_SESSION_FROM_IP_POOL,
838       entry_list[0].type);
839 
840   // Both FindAvailableSession() calls (including one from
841   // TryCreateAliasedSpdySession) should log histogram entries indicating IP
842   // pooling.
843   histogram_tester.ExpectUniqueSample("Net.SpdySessionGet", 2, 2);
844 }
845 
846 // Test IP pooling when the DNS responses have ALPNs.
TEST_F(SpdySessionPoolTest,IPPoolingDnsAlpn)847 TEST_F(SpdySessionPoolTest, IPPoolingDnsAlpn) {
848   // Define two hosts with identical IP address.
849   constexpr int kTestPort = 443;
850   struct TestHosts {
851     std::string name;
852     std::vector<HostResolverEndpointResult> endpoints;
853     SpdySessionKey key;
854   } test_hosts[] = {{"www.example.org"},
855                     {"mail.example.org"},
856                     {"mail.example.com"},
857                     {"example.test"}};
858 
859   const IPEndPoint kRightIP(*IPAddress::FromIPLiteral("192.168.0.1"),
860                             kTestPort);
861   const IPEndPoint kWrongIP(*IPAddress::FromIPLiteral("192.168.0.2"),
862                             kTestPort);
863   const std::string kRightALPN = "h2";
864   const std::string kWrongALPN = "h3";
865 
866   // `test_hosts[0]` and `test_hosts[1]` resolve to the same IP address, without
867   // any ALPN information.
868   test_hosts[0].endpoints.emplace_back();
869   test_hosts[0].endpoints[0].ip_endpoints = {kRightIP};
870   test_hosts[1].endpoints.emplace_back();
871   test_hosts[1].endpoints[0].ip_endpoints = {kRightIP};
872 
873   // `test_hosts[2]` resolves to the same IP address, but only via an
874   // alternative endpoint with matching ALPN.
875   test_hosts[2].endpoints.emplace_back();
876   test_hosts[2].endpoints[0].ip_endpoints = {kRightIP};
877   test_hosts[2].endpoints[0].metadata.supported_protocol_alpns = {kRightALPN};
878 
879   // `test_hosts[3]` resolves to the same IP address, but only via an
880   // alternative endpoint with a mismatching ALPN.
881   test_hosts[3].endpoints.resize(2);
882   test_hosts[3].endpoints[0].ip_endpoints = {kRightIP};
883   test_hosts[3].endpoints[0].metadata.supported_protocol_alpns = {kWrongALPN};
884   test_hosts[3].endpoints[1].ip_endpoints = {kWrongIP};
885   test_hosts[3].endpoints[1].metadata.supported_protocol_alpns = {kRightALPN};
886 
887   // Populate the HostResolver cache.
888   session_deps_.host_resolver->set_synchronous_mode(true);
889   for (auto& test_host : test_hosts) {
890     session_deps_.host_resolver->rules()->AddRule(
891         test_host.name,
892         MockHostResolverBase::RuleResolver::RuleResult(test_host.endpoints));
893 
894     test_host.key = SpdySessionKey(
895         HostPortPair(test_host.name, kTestPort), ProxyChain::Direct(),
896         PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
897         SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
898   }
899 
900   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
901   StaticSocketDataProvider data(reads, base::span<MockWrite>());
902   MockConnect connect_data(SYNCHRONOUS, OK);
903   data.set_connect_data(connect_data);
904 
905   session_deps_.socket_factory->AddSocketDataProvider(&data);
906   AddSSLSocketData();
907 
908   CreateNetworkSession();
909 
910   // Open SpdySession to the first host.
911   base::WeakPtr<SpdySession> session0 = CreateSpdySession(
912       http_session_.get(), test_hosts[0].key, NetLogWithSource());
913 
914   // The second host should pool to the existing connection. Although the
915   // addresses are not associated with ALPNs, the default connection flow for
916   // HTTPS is compatible with HTTP/2.
917   EXPECT_TRUE(TryCreateAliasedSpdySession(spdy_session_pool_, test_hosts[1].key,
918                                           test_hosts[1].endpoints));
919   base::WeakPtr<SpdySession> session1 =
920       spdy_session_pool_->FindAvailableSession(
921           test_hosts[1].key, /*enable_ip_based_pooling=*/true,
922           /*is_websocket=*/false,
923           NetLogWithSource::Make(NetLogSourceType::NONE));
924   EXPECT_EQ(session0.get(), session1.get());
925 
926   // The third host should also pool to the existing connection.
927   EXPECT_TRUE(TryCreateAliasedSpdySession(spdy_session_pool_, test_hosts[2].key,
928                                           test_hosts[2].endpoints));
929   base::WeakPtr<SpdySession> session2 =
930       spdy_session_pool_->FindAvailableSession(
931           test_hosts[2].key, /*enable_ip_based_pooling=*/true,
932           /*is_websocket=*/false,
933           NetLogWithSource::Make(NetLogSourceType::NONE));
934   EXPECT_EQ(session0.get(), session2.get());
935 
936   // The fourth host should not pool. The only matching endpoint is specific to
937   // QUIC.
938   EXPECT_FALSE(TryCreateAliasedSpdySession(
939       spdy_session_pool_, test_hosts[3].key, test_hosts[3].endpoints));
940 }
941 
TEST_F(SpdySessionPoolTest,IPPoolingDisabled)942 TEST_F(SpdySessionPoolTest, IPPoolingDisabled) {
943   // Define two hosts with identical IP address.
944   constexpr int kTestPort = 443;
945   struct TestHosts {
946     std::string name;
947     std::string iplist;
948     SpdySessionKey key;
949   } test_hosts[] = {
950       {"www.example.org", "192.168.0.1"}, {"mail.example.org", "192.168.0.1"},
951   };
952 
953   // Populate the HostResolver cache.
954   session_deps_.host_resolver->set_synchronous_mode(true);
955   for (auto& test_host : test_hosts) {
956     session_deps_.host_resolver->rules()->AddIPLiteralRule(
957         test_host.name, test_host.iplist, std::string());
958 
959     test_host.key = SpdySessionKey(
960         HostPortPair(test_host.name, kTestPort), ProxyChain::Direct(),
961         PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
962         SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
963   }
964 
965   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
966   StaticSocketDataProvider data(reads, base::span<MockWrite>());
967   MockConnect connect_data(SYNCHRONOUS, OK);
968   data.set_connect_data(connect_data);
969   session_deps_.socket_factory->AddSocketDataProvider(&data);
970   AddSSLSocketData();
971 
972   MockRead reads1[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
973   StaticSocketDataProvider data1(reads1, base::span<MockWrite>());
974   MockConnect connect_data1(SYNCHRONOUS, OK);
975   data1.set_connect_data(connect_data1);
976   session_deps_.socket_factory->AddSocketDataProvider(&data1);
977   AddSSLSocketData();
978 
979   CreateNetworkSession();
980 
981   // Open SpdySession to the first host.
982   base::WeakPtr<SpdySession> session0 = CreateSpdySession(
983       http_session_.get(), test_hosts[0].key, NetLogWithSource());
984 
985   // |test_hosts[1]| should pool to the existing connection.
986   EXPECT_TRUE(TryCreateAliasedSpdySession(spdy_session_pool_, test_hosts[1].key,
987                                           test_hosts[1].iplist));
988   base::WeakPtr<SpdySession> session1 =
989       spdy_session_pool_->FindAvailableSession(
990           test_hosts[1].key, /* enable_ip_based_pooling = */ true,
991           /* is_websocket = */ false, NetLogWithSource());
992   EXPECT_EQ(session0.get(), session1.get());
993 
994   // A request to the second host should not pool to the existing connection if
995   // IP based pooling is disabled.
996   session1 = spdy_session_pool_->FindAvailableSession(
997       test_hosts[1].key, /* enable_ip_based_pooling = */ false,
998       /* is_websocket = */ false, NetLogWithSource());
999   EXPECT_FALSE(session1);
1000 
1001   // It should be possible to open a new SpdySession, even if a previous call to
1002   // FindAvailableSession() linked the second key to the first connection in the
1003   // IP pooled bucket of SpdySessionPool::available_session_map_.
1004   session1 = CreateSpdySessionWithIpBasedPoolingDisabled(
1005       http_session_.get(), test_hosts[1].key, NetLogWithSource());
1006   EXPECT_TRUE(session1);
1007   EXPECT_NE(session0.get(), session1.get());
1008 }
1009 
1010 // Verifies that an SSL connection with client authentication disables SPDY IP
1011 // pooling.
TEST_F(SpdySessionPoolTest,IPPoolingClientCert)1012 TEST_F(SpdySessionPoolTest, IPPoolingClientCert) {
1013   SSLSocketDataProvider ssl(ASYNC, OK);
1014   ssl.ssl_info.cert = X509Certificate::CreateFromBytes(webkit_der);
1015   ASSERT_TRUE(ssl.ssl_info.cert);
1016   ssl.ssl_info.client_cert_sent = true;
1017   ssl.next_proto = kProtoHTTP2;
1018   RunIPPoolingDisabledTest(&ssl);
1019 }
1020 
1021 namespace {
1022 enum class ChangeType {
1023   kIpAddress = 0,
1024   kSSLConfig,
1025   kCertDatabase,
1026   kCertVerifier
1027 };
1028 
1029 class SpdySessionGoAwayOnChangeTest
1030     : public SpdySessionPoolTest,
1031       public ::testing::WithParamInterface<ChangeType> {
1032  public:
SetUp()1033   void SetUp() override {
1034     SpdySessionPoolTest::SetUp();
1035 
1036     if (GetParam() == ChangeType::kIpAddress) {
1037       session_deps_.go_away_on_ip_change = true;
1038     }
1039   }
1040 
SimulateChange()1041   void SimulateChange() {
1042     switch (GetParam()) {
1043       case ChangeType::kIpAddress:
1044         spdy_session_pool_->OnIPAddressChanged();
1045         break;
1046       case ChangeType::kSSLConfig:
1047         session_deps_.ssl_config_service->NotifySSLContextConfigChange();
1048         break;
1049       case ChangeType::kCertDatabase:
1050         // TODO(mattm): For more realistic testing this should call
1051         // `CertDatabase::GetInstance()->NotifyObserversCertDBChanged()`,
1052         // however that delivers notifications asynchronously, and running
1053         // the message loop to allow the notification to be delivered allows
1054         // other parts of the tested code to advance, breaking the test
1055         // expectations.
1056         spdy_session_pool_->OnSSLConfigChanged(
1057             SSLClientContext::SSLConfigChangeType::kCertDatabaseChanged);
1058         break;
1059       case ChangeType::kCertVerifier:
1060         session_deps_.cert_verifier->SimulateOnCertVerifierChanged();
1061         break;
1062     }
1063   }
1064 
ExpectedNetError() const1065   Error ExpectedNetError() const {
1066     switch (GetParam()) {
1067       case ChangeType::kIpAddress:
1068         return ERR_NETWORK_CHANGED;
1069       case ChangeType::kSSLConfig:
1070         return ERR_NETWORK_CHANGED;
1071       case ChangeType::kCertDatabase:
1072         return ERR_CERT_DATABASE_CHANGED;
1073       case ChangeType::kCertVerifier:
1074         return ERR_CERT_VERIFIER_CHANGED;
1075     }
1076   }
1077 };
1078 }  // namespace
1079 
1080 // Construct a Pool with SpdySessions in various availability states. Simulate
1081 // an IP address change. Ensure sessions gracefully shut down. Regression test
1082 // for crbug.com/379469.
TEST_P(SpdySessionGoAwayOnChangeTest,GoAwayOnChange)1083 TEST_P(SpdySessionGoAwayOnChangeTest, GoAwayOnChange) {
1084   MockConnect connect_data(SYNCHRONOUS, OK);
1085   session_deps_.host_resolver->set_synchronous_mode(true);
1086 
1087   // This isn't testing anything having to do with SPDY frames; we
1088   // can ignore issues of how dependencies are set.  We default to
1089   // setting them (when doing the appropriate protocol) since that's
1090   // where we're eventually headed for all HTTP/2 connections.
1091   SpdyTestUtil spdy_util;
1092 
1093   MockRead reads[] = {
1094       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1095   };
1096   spdy::SpdySerializedFrame req(
1097       spdy_util.ConstructSpdyGet("http://www.example.org", 1, MEDIUM));
1098   MockWrite writes[] = {CreateMockWrite(req, 1)};
1099 
1100   StaticSocketDataProvider dataA(reads, writes);
1101   dataA.set_connect_data(connect_data);
1102   session_deps_.socket_factory->AddSocketDataProvider(&dataA);
1103 
1104   AddSSLSocketData();
1105 
1106   CreateNetworkSession();
1107 
1108   // Set up session A: Going away, but with an active stream.
1109   const std::string kTestHostA("www.example.org");
1110   HostPortPair test_host_port_pairA(kTestHostA, 80);
1111   SpdySessionKey keyA(test_host_port_pairA, ProxyChain::Direct(),
1112                       PRIVACY_MODE_DISABLED,
1113                       SpdySessionKey::IsProxySession::kFalse, SocketTag(),
1114                       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1115   base::WeakPtr<SpdySession> sessionA =
1116       CreateSpdySession(http_session_.get(), keyA, NetLogWithSource());
1117 
1118   GURL urlA("http://www.example.org");
1119   base::WeakPtr<SpdyStream> spdy_streamA = CreateStreamSynchronously(
1120       SPDY_BIDIRECTIONAL_STREAM, sessionA, urlA, MEDIUM, NetLogWithSource());
1121   test::StreamDelegateDoNothing delegateA(spdy_streamA);
1122   spdy_streamA->SetDelegate(&delegateA);
1123 
1124   spdy::Http2HeaderBlock headers(
1125       spdy_util.ConstructGetHeaderBlock(urlA.spec()));
1126   spdy_streamA->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1127 
1128   base::RunLoop().RunUntilIdle();  // Allow headers to write.
1129   EXPECT_TRUE(delegateA.send_headers_completed());
1130 
1131   sessionA->MakeUnavailable();
1132   EXPECT_TRUE(sessionA->IsGoingAway());
1133   EXPECT_FALSE(delegateA.StreamIsClosed());
1134 
1135   // Set up session B: Available, with a created stream.
1136   StaticSocketDataProvider dataB(reads, writes);
1137   dataB.set_connect_data(connect_data);
1138   session_deps_.socket_factory->AddSocketDataProvider(&dataB);
1139 
1140   AddSSLSocketData();
1141 
1142   const std::string kTestHostB("mail.example.org");
1143   HostPortPair test_host_port_pairB(kTestHostB, 80);
1144   SpdySessionKey keyB(test_host_port_pairB, ProxyChain::Direct(),
1145                       PRIVACY_MODE_DISABLED,
1146                       SpdySessionKey::IsProxySession::kFalse, SocketTag(),
1147                       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1148   base::WeakPtr<SpdySession> sessionB =
1149       CreateSpdySession(http_session_.get(), keyB, NetLogWithSource());
1150   EXPECT_TRUE(sessionB->IsAvailable());
1151 
1152   GURL urlB("http://mail.example.org");
1153   base::WeakPtr<SpdyStream> spdy_streamB = CreateStreamSynchronously(
1154       SPDY_BIDIRECTIONAL_STREAM, sessionB, urlB, MEDIUM, NetLogWithSource());
1155   test::StreamDelegateDoNothing delegateB(spdy_streamB);
1156   spdy_streamB->SetDelegate(&delegateB);
1157 
1158   // Set up session C: Draining.
1159   StaticSocketDataProvider dataC(reads, writes);
1160   dataC.set_connect_data(connect_data);
1161   session_deps_.socket_factory->AddSocketDataProvider(&dataC);
1162 
1163   AddSSLSocketData();
1164 
1165   const std::string kTestHostC("mail.example.com");
1166   HostPortPair test_host_port_pairC(kTestHostC, 80);
1167   SpdySessionKey keyC(test_host_port_pairC, ProxyChain::Direct(),
1168                       PRIVACY_MODE_DISABLED,
1169                       SpdySessionKey::IsProxySession::kFalse, SocketTag(),
1170                       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1171   base::WeakPtr<SpdySession> sessionC =
1172       CreateSpdySession(http_session_.get(), keyC, NetLogWithSource());
1173 
1174   sessionC->CloseSessionOnError(ERR_HTTP2_PROTOCOL_ERROR, "Error!");
1175   EXPECT_TRUE(sessionC->IsDraining());
1176 
1177   SimulateChange();
1178 
1179   EXPECT_TRUE(sessionA->IsGoingAway());
1180   EXPECT_TRUE(sessionB->IsDraining());
1181   EXPECT_TRUE(sessionC->IsDraining());
1182 
1183   EXPECT_EQ(1u,
1184             num_active_streams(sessionA));  // Active stream is still active.
1185   EXPECT_FALSE(delegateA.StreamIsClosed());
1186 
1187   EXPECT_TRUE(delegateB.StreamIsClosed());  // Created stream was closed.
1188   EXPECT_THAT(delegateB.WaitForClose(), IsError(ExpectedNetError()));
1189 
1190   sessionA->CloseSessionOnError(ERR_ABORTED, "Closing");
1191   sessionB->CloseSessionOnError(ERR_ABORTED, "Closing");
1192 
1193   EXPECT_TRUE(delegateA.StreamIsClosed());
1194   EXPECT_THAT(delegateA.WaitForClose(), IsError(ERR_ABORTED));
1195 }
1196 
1197 INSTANTIATE_TEST_SUITE_P(All,
1198                          SpdySessionGoAwayOnChangeTest,
1199                          testing::Values(ChangeType::kIpAddress,
1200                                          ChangeType::kSSLConfig,
1201                                          ChangeType::kCertDatabase,
1202                                          ChangeType::kCertVerifier));
1203 
1204 // Construct a Pool with SpdySessions in various availability states. Simulate
1205 // an IP address change. Ensure sessions gracefully shut down. Regression test
1206 // for crbug.com/379469.
TEST_F(SpdySessionPoolTest,CloseOnIPAddressChanged)1207 TEST_F(SpdySessionPoolTest, CloseOnIPAddressChanged) {
1208   MockConnect connect_data(SYNCHRONOUS, OK);
1209   session_deps_.host_resolver->set_synchronous_mode(true);
1210 
1211   // This isn't testing anything having to do with SPDY frames; we
1212   // can ignore issues of how dependencies are set.  We default to
1213   // setting them (when doing the appropriate protocol) since that's
1214   // where we're eventually headed for all HTTP/2 connections.
1215   SpdyTestUtil spdy_util;
1216 
1217   MockRead reads[] = {
1218       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1219   };
1220   spdy::SpdySerializedFrame req(
1221       spdy_util.ConstructSpdyGet("http://www.example.org", 1, MEDIUM));
1222   MockWrite writes[] = {CreateMockWrite(req, 1)};
1223 
1224   StaticSocketDataProvider dataA(reads, writes);
1225   dataA.set_connect_data(connect_data);
1226   session_deps_.socket_factory->AddSocketDataProvider(&dataA);
1227 
1228   AddSSLSocketData();
1229 
1230   session_deps_.go_away_on_ip_change = false;
1231   CreateNetworkSession();
1232 
1233   // Set up session A: Going away, but with an active stream.
1234   const std::string kTestHostA("www.example.org");
1235   HostPortPair test_host_port_pairA(kTestHostA, 80);
1236   SpdySessionKey keyA(test_host_port_pairA, ProxyChain::Direct(),
1237                       PRIVACY_MODE_DISABLED,
1238                       SpdySessionKey::IsProxySession::kFalse, SocketTag(),
1239                       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1240   base::WeakPtr<SpdySession> sessionA =
1241       CreateSpdySession(http_session_.get(), keyA, NetLogWithSource());
1242 
1243   GURL urlA("http://www.example.org");
1244   base::WeakPtr<SpdyStream> spdy_streamA = CreateStreamSynchronously(
1245       SPDY_BIDIRECTIONAL_STREAM, sessionA, urlA, MEDIUM, NetLogWithSource());
1246   test::StreamDelegateDoNothing delegateA(spdy_streamA);
1247   spdy_streamA->SetDelegate(&delegateA);
1248 
1249   spdy::Http2HeaderBlock headers(
1250       spdy_util.ConstructGetHeaderBlock(urlA.spec()));
1251   spdy_streamA->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1252 
1253   base::RunLoop().RunUntilIdle();  // Allow headers to write.
1254   EXPECT_TRUE(delegateA.send_headers_completed());
1255 
1256   sessionA->MakeUnavailable();
1257   EXPECT_TRUE(sessionA->IsGoingAway());
1258   EXPECT_FALSE(delegateA.StreamIsClosed());
1259 
1260   // Set up session B: Available, with a created stream.
1261   StaticSocketDataProvider dataB(reads, writes);
1262   dataB.set_connect_data(connect_data);
1263   session_deps_.socket_factory->AddSocketDataProvider(&dataB);
1264 
1265   AddSSLSocketData();
1266 
1267   const std::string kTestHostB("mail.example.org");
1268   HostPortPair test_host_port_pairB(kTestHostB, 80);
1269   SpdySessionKey keyB(test_host_port_pairB, ProxyChain::Direct(),
1270                       PRIVACY_MODE_DISABLED,
1271                       SpdySessionKey::IsProxySession::kFalse, SocketTag(),
1272                       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1273   base::WeakPtr<SpdySession> sessionB =
1274       CreateSpdySession(http_session_.get(), keyB, NetLogWithSource());
1275   EXPECT_TRUE(sessionB->IsAvailable());
1276 
1277   GURL urlB("http://mail.example.org");
1278   base::WeakPtr<SpdyStream> spdy_streamB = CreateStreamSynchronously(
1279       SPDY_BIDIRECTIONAL_STREAM, sessionB, urlB, MEDIUM, NetLogWithSource());
1280   test::StreamDelegateDoNothing delegateB(spdy_streamB);
1281   spdy_streamB->SetDelegate(&delegateB);
1282 
1283   // Set up session C: Draining.
1284   StaticSocketDataProvider dataC(reads, writes);
1285   dataC.set_connect_data(connect_data);
1286   session_deps_.socket_factory->AddSocketDataProvider(&dataC);
1287 
1288   AddSSLSocketData();
1289 
1290   const std::string kTestHostC("mail.example.com");
1291   HostPortPair test_host_port_pairC(kTestHostC, 80);
1292   SpdySessionKey keyC(test_host_port_pairC, ProxyChain::Direct(),
1293                       PRIVACY_MODE_DISABLED,
1294                       SpdySessionKey::IsProxySession::kFalse, SocketTag(),
1295                       NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1296   base::WeakPtr<SpdySession> sessionC =
1297       CreateSpdySession(http_session_.get(), keyC, NetLogWithSource());
1298 
1299   sessionC->CloseSessionOnError(ERR_HTTP2_PROTOCOL_ERROR, "Error!");
1300   EXPECT_TRUE(sessionC->IsDraining());
1301 
1302   spdy_session_pool_->OnIPAddressChanged();
1303 
1304   EXPECT_TRUE(sessionA->IsDraining());
1305   EXPECT_TRUE(sessionB->IsDraining());
1306   EXPECT_TRUE(sessionC->IsDraining());
1307 
1308   // Both streams were closed with an error.
1309   EXPECT_TRUE(delegateA.StreamIsClosed());
1310   EXPECT_THAT(delegateA.WaitForClose(), IsError(ERR_NETWORK_CHANGED));
1311   EXPECT_TRUE(delegateB.StreamIsClosed());
1312   EXPECT_THAT(delegateB.WaitForClose(), IsError(ERR_NETWORK_CHANGED));
1313 }
1314 
1315 // Regression test for https://crbug.com/789791.
TEST_F(SpdySessionPoolTest,HandleIPAddressChangeThenShutdown)1316 TEST_F(SpdySessionPoolTest, HandleIPAddressChangeThenShutdown) {
1317   MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
1318   SpdyTestUtil spdy_util;
1319   spdy::SpdySerializedFrame req(
1320       spdy_util.ConstructSpdyGet(kDefaultUrl, 1, MEDIUM));
1321   MockWrite writes[] = {CreateMockWrite(req, 1)};
1322   StaticSocketDataProvider data(reads, writes);
1323 
1324   MockConnect connect_data(SYNCHRONOUS, OK);
1325   data.set_connect_data(connect_data);
1326 
1327   session_deps_.socket_factory->AddSocketDataProvider(&data);
1328   AddSSLSocketData();
1329 
1330   CreateNetworkSession();
1331 
1332   const GURL url(kDefaultUrl);
1333   SpdySessionKey key(HostPortPair::FromURL(url), ProxyChain::Direct(),
1334                      PRIVACY_MODE_DISABLED,
1335                      SpdySessionKey::IsProxySession::kFalse, SocketTag(),
1336                      NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1337   base::WeakPtr<SpdySession> session =
1338       CreateSpdySession(http_session_.get(), key, NetLogWithSource());
1339 
1340   base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1341       SPDY_BIDIRECTIONAL_STREAM, session, url, MEDIUM, NetLogWithSource());
1342   test::StreamDelegateDoNothing delegate(spdy_stream);
1343   spdy_stream->SetDelegate(&delegate);
1344 
1345   spdy::Http2HeaderBlock headers(spdy_util.ConstructGetHeaderBlock(url.spec()));
1346   spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1347 
1348   base::RunLoop().RunUntilIdle();
1349   EXPECT_TRUE(delegate.send_headers_completed());
1350 
1351   spdy_session_pool_->OnIPAddressChanged();
1352 
1353 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
1354   EXPECT_EQ(1u, num_active_streams(session));
1355   EXPECT_TRUE(session->IsGoingAway());
1356   EXPECT_FALSE(session->IsDraining());
1357 #else
1358   EXPECT_EQ(0u, num_active_streams(session));
1359   EXPECT_FALSE(session->IsGoingAway());
1360   EXPECT_TRUE(session->IsDraining());
1361 #endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
1362 
1363   http_session_.reset();
1364 
1365   data.AllReadDataConsumed();
1366   data.AllWriteDataConsumed();
1367 }
1368 
1369 // Regression test for https://crbug.com/789791.
TEST_F(SpdySessionPoolTest,HandleGracefulGoawayThenShutdown)1370 TEST_F(SpdySessionPoolTest, HandleGracefulGoawayThenShutdown) {
1371   SpdyTestUtil spdy_util;
1372   spdy::SpdySerializedFrame goaway(spdy_util.ConstructSpdyGoAway(
1373       0x7fffffff, spdy::ERROR_CODE_NO_ERROR, "Graceful shutdown."));
1374   MockRead reads[] = {
1375       MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(goaway, 2),
1376       MockRead(ASYNC, ERR_IO_PENDING, 3), MockRead(ASYNC, OK, 4)};
1377   spdy::SpdySerializedFrame req(
1378       spdy_util.ConstructSpdyGet(kDefaultUrl, 1, MEDIUM));
1379   MockWrite writes[] = {CreateMockWrite(req, 0)};
1380   SequencedSocketData data(reads, writes);
1381 
1382   MockConnect connect_data(SYNCHRONOUS, OK);
1383   data.set_connect_data(connect_data);
1384 
1385   session_deps_.socket_factory->AddSocketDataProvider(&data);
1386   AddSSLSocketData();
1387 
1388   CreateNetworkSession();
1389 
1390   const GURL url(kDefaultUrl);
1391   SpdySessionKey key(HostPortPair::FromURL(url), ProxyChain::Direct(),
1392                      PRIVACY_MODE_DISABLED,
1393                      SpdySessionKey::IsProxySession::kFalse, SocketTag(),
1394                      NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1395   base::WeakPtr<SpdySession> session =
1396       CreateSpdySession(http_session_.get(), key, NetLogWithSource());
1397 
1398   base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1399       SPDY_BIDIRECTIONAL_STREAM, session, url, MEDIUM, NetLogWithSource());
1400   test::StreamDelegateDoNothing delegate(spdy_stream);
1401   spdy_stream->SetDelegate(&delegate);
1402 
1403   spdy::Http2HeaderBlock headers(spdy_util.ConstructGetHeaderBlock(url.spec()));
1404   spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1405 
1406   // Send headers.
1407   base::RunLoop().RunUntilIdle();
1408   EXPECT_TRUE(delegate.send_headers_completed());
1409 
1410   EXPECT_EQ(1u, num_active_streams(session));
1411   EXPECT_FALSE(session->IsGoingAway());
1412   EXPECT_FALSE(session->IsDraining());
1413 
1414   // Read GOAWAY.
1415   data.Resume();
1416   base::RunLoop().RunUntilIdle();
1417 
1418   EXPECT_EQ(1u, num_active_streams(session));
1419   EXPECT_TRUE(session->IsGoingAway());
1420   EXPECT_FALSE(session->IsDraining());
1421 
1422   http_session_.reset();
1423 
1424   data.AllReadDataConsumed();
1425   data.AllWriteDataConsumed();
1426 }
1427 
TEST_F(SpdySessionPoolTest,IPConnectionPoolingWithWebSockets)1428 TEST_F(SpdySessionPoolTest, IPConnectionPoolingWithWebSockets) {
1429   // Define two hosts with identical IP address.
1430   const int kTestPort = 443;
1431   struct TestHosts {
1432     std::string name;
1433     std::string iplist;
1434     SpdySessionKey key;
1435   } test_hosts[] = {
1436       {"www.example.org", "192.168.0.1"}, {"mail.example.org", "192.168.0.1"},
1437   };
1438 
1439   // Populate the HostResolver cache.
1440   session_deps_.host_resolver->set_synchronous_mode(true);
1441   for (auto& test_host : test_hosts) {
1442     session_deps_.host_resolver->rules()->AddIPLiteralRule(
1443         test_host.name, test_host.iplist, std::string());
1444 
1445     test_host.key = SpdySessionKey(
1446         HostPortPair(test_host.name, kTestPort), ProxyChain::Direct(),
1447         PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
1448         SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1449   }
1450 
1451   SpdyTestUtil spdy_util;
1452 
1453   spdy::SpdySerializedFrame req(
1454       spdy_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
1455   spdy::SpdySerializedFrame settings_ack(spdy_util.ConstructSpdySettingsAck());
1456   MockWrite writes[] = {CreateMockWrite(req, 0),
1457                         CreateMockWrite(settings_ack, 2)};
1458 
1459   spdy::SettingsMap settings;
1460   settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
1461   spdy::SpdySerializedFrame settings_frame(
1462       spdy_util.ConstructSpdySettings(settings));
1463   spdy::SpdySerializedFrame resp(
1464       spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
1465   spdy::SpdySerializedFrame body(spdy_util.ConstructSpdyDataFrame(1, true));
1466   MockRead reads[] = {CreateMockRead(settings_frame, 1),
1467                       CreateMockRead(resp, 3), CreateMockRead(body, 4),
1468                       MockRead(ASYNC, ERR_IO_PENDING, 5),
1469                       MockRead(ASYNC, 0, 6)};
1470 
1471   SequencedSocketData data(reads, writes);
1472   session_deps_.socket_factory->AddSocketDataProvider(&data);
1473   AddSSLSocketData();
1474   CreateNetworkSession();
1475 
1476   // Create a connection to the first host.
1477   base::WeakPtr<SpdySession> session = CreateSpdySession(
1478       http_session_.get(), test_hosts[0].key, NetLogWithSource());
1479 
1480   // SpdySession does not support Websocket before SETTINGS frame is read.
1481   EXPECT_FALSE(session->support_websocket());
1482   NetLogWithSource net_log_with_source{
1483       NetLogWithSource::Make(NetLogSourceType::NONE)};
1484   // TryCreateAliasedSpdySession should not find |session| for either
1485   // SpdySessionKeys if |is_websocket| argument is set.
1486   EXPECT_FALSE(TryCreateAliasedSpdySession(
1487       spdy_session_pool_, test_hosts[0].key, test_hosts[0].iplist,
1488       /* enable_ip_based_pooling = */ true,
1489       /* is_websocket = */ true));
1490   EXPECT_FALSE(TryCreateAliasedSpdySession(
1491       spdy_session_pool_, test_hosts[1].key, test_hosts[1].iplist,
1492       /* enable_ip_based_pooling = */ true,
1493       /* is_websocket = */ true));
1494 
1495   // Start request that triggers reading the SETTINGS frame.
1496   const GURL url(kDefaultUrl);
1497   base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously(
1498       SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, NetLogWithSource());
1499   test::StreamDelegateDoNothing delegate(spdy_stream);
1500   spdy_stream->SetDelegate(&delegate);
1501 
1502   spdy::Http2HeaderBlock headers(spdy_util.ConstructGetHeaderBlock(url.spec()));
1503   spdy_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1504 
1505   base::RunLoop().RunUntilIdle();
1506 
1507   // Now SpdySession has read the SETTINGS frame and thus supports Websocket.
1508   EXPECT_TRUE(session->support_websocket());
1509 
1510   // FindAvailableSession() on the first host should now find the existing
1511   // session with websockets enabled, and TryCreateAliasedSpdySession() should
1512   // now set up aliases for |session| for the second one.
1513   base::WeakPtr<SpdySession> result = spdy_session_pool_->FindAvailableSession(
1514       test_hosts[0].key, /* enable_ip_based_pooling = */ true,
1515       /* is_websocket = */ true, net_log_with_source);
1516   EXPECT_EQ(session.get(), result.get());
1517   EXPECT_TRUE(TryCreateAliasedSpdySession(spdy_session_pool_, test_hosts[1].key,
1518                                           test_hosts[1].iplist,
1519                                           /* enable_ip_based_pooling = */ true,
1520                                           /* is_websocket = */ true));
1521 
1522   // FindAvailableSession() should return |session| for either SpdySessionKeys
1523   // when IP based pooling is enabled.
1524   result = spdy_session_pool_->FindAvailableSession(
1525       test_hosts[0].key, /* enable_ip_based_pooling = */ true,
1526       /* is_websocket = */ true, net_log_with_source);
1527   EXPECT_EQ(session.get(), result.get());
1528   result = spdy_session_pool_->FindAvailableSession(
1529       test_hosts[1].key, /* enable_ip_based_pooling = */ true,
1530       /* is_websocket = */ true, net_log_with_source);
1531   EXPECT_EQ(session.get(), result.get());
1532 
1533   // FindAvailableSession() should only return |session| for the first
1534   // SpdySessionKey when IP based pooling is disabled.
1535   result = spdy_session_pool_->FindAvailableSession(
1536       test_hosts[0].key, /* enable_ip_based_pooling = */ false,
1537       /* is_websocket = */ true, net_log_with_source);
1538   EXPECT_EQ(session.get(), result.get());
1539   result = spdy_session_pool_->FindAvailableSession(
1540       test_hosts[1].key, /* enable_ip_based_pooling = */ false,
1541       /* is_websocket = */ true, net_log_with_source);
1542   EXPECT_FALSE(result);
1543 
1544   // Read EOF.
1545   data.Resume();
1546   base::RunLoop().RunUntilIdle();
1547 
1548   EXPECT_TRUE(data.AllReadDataConsumed());
1549   EXPECT_TRUE(data.AllWriteDataConsumed());
1550 }
1551 
1552 class TestOnRequestDeletedCallback {
1553  public:
1554   TestOnRequestDeletedCallback() = default;
1555 
1556   TestOnRequestDeletedCallback(const TestOnRequestDeletedCallback&) = delete;
1557   TestOnRequestDeletedCallback& operator=(const TestOnRequestDeletedCallback&) =
1558       delete;
1559 
1560   ~TestOnRequestDeletedCallback() = default;
1561 
Callback()1562   base::RepeatingClosure Callback() {
1563     return base::BindRepeating(&TestOnRequestDeletedCallback::OnRequestDeleted,
1564                                base::Unretained(this));
1565   }
1566 
invoked() const1567   bool invoked() const { return invoked_; }
1568 
WaitUntilInvoked()1569   void WaitUntilInvoked() { run_loop_.Run(); }
1570 
SetRequestDeletedCallback(base::OnceClosure request_deleted_callback)1571   void SetRequestDeletedCallback(base::OnceClosure request_deleted_callback) {
1572     DCHECK(!request_deleted_callback_);
1573     request_deleted_callback_ = std::move(request_deleted_callback);
1574   }
1575 
1576  private:
OnRequestDeleted()1577   void OnRequestDeleted() {
1578     EXPECT_FALSE(invoked_);
1579     invoked_ = true;
1580     if (request_deleted_callback_)
1581       std::move(request_deleted_callback_).Run();
1582     run_loop_.Quit();
1583   }
1584 
1585   bool invoked_ = false;
1586   base::RunLoop run_loop_;
1587 
1588   base::OnceClosure request_deleted_callback_;
1589 };
1590 
1591 class TestRequestDelegate
1592     : public SpdySessionPool::SpdySessionRequest::Delegate {
1593  public:
1594   TestRequestDelegate() = default;
1595 
1596   TestRequestDelegate(const TestRequestDelegate&) = delete;
1597   TestRequestDelegate& operator=(const TestRequestDelegate&) = delete;
1598 
1599   ~TestRequestDelegate() override = default;
1600 
1601   // SpdySessionPool::SpdySessionRequest::Delegate implementation:
OnSpdySessionAvailable(base::WeakPtr<SpdySession> spdy_session)1602   void OnSpdySessionAvailable(
1603       base::WeakPtr<SpdySession> spdy_session) override {}
1604 };
1605 
TEST_F(SpdySessionPoolTest,RequestSessionWithNoSessions)1606 TEST_F(SpdySessionPoolTest, RequestSessionWithNoSessions) {
1607   const SpdySessionKey kSessionKey(
1608       HostPortPair("foo.test", 443), ProxyChain::Direct(),
1609       PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
1610       SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1611 
1612   CreateNetworkSession();
1613 
1614   // First request. Its request deleted callback should never be invoked.
1615   TestOnRequestDeletedCallback request_deleted_callback1;
1616   TestRequestDelegate request_delegate1;
1617   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request1;
1618   bool is_first_request_for_session;
1619   EXPECT_FALSE(spdy_session_pool_->RequestSession(
1620       kSessionKey, /* enable_ip_based_pooling = */ false,
1621       /* is_websocket = */ false, NetLogWithSource(),
1622       request_deleted_callback1.Callback(), &request_delegate1,
1623       &spdy_session_request1, &is_first_request_for_session));
1624   EXPECT_TRUE(is_first_request_for_session);
1625 
1626   // Second request.
1627   TestOnRequestDeletedCallback request_deleted_callback2;
1628   TestRequestDelegate request_delegate2;
1629   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request2;
1630   EXPECT_FALSE(spdy_session_pool_->RequestSession(
1631       kSessionKey, /* enable_ip_based_pooling = */ false,
1632       /* is_websocket = */ false, NetLogWithSource(),
1633       request_deleted_callback2.Callback(), &request_delegate2,
1634       &spdy_session_request2, &is_first_request_for_session));
1635   EXPECT_FALSE(is_first_request_for_session);
1636 
1637   // Third request.
1638   TestOnRequestDeletedCallback request_deleted_callback3;
1639   TestRequestDelegate request_delegate3;
1640   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request3;
1641   EXPECT_FALSE(spdy_session_pool_->RequestSession(
1642       kSessionKey, /* enable_ip_based_pooling = */ false,
1643       /* is_websocket = */ false, NetLogWithSource(),
1644       request_deleted_callback3.Callback(), &request_delegate3,
1645       &spdy_session_request3, &is_first_request_for_session));
1646   EXPECT_FALSE(is_first_request_for_session);
1647 
1648   // Destroying the second request shouldn't cause anything to happen.
1649   spdy_session_request2.reset();
1650   base::RunLoop().RunUntilIdle();
1651   EXPECT_FALSE(request_deleted_callback1.invoked());
1652   EXPECT_FALSE(request_deleted_callback2.invoked());
1653   EXPECT_FALSE(request_deleted_callback3.invoked());
1654 
1655   // But destroying the first request should cause the second and third
1656   // callbacks to be invoked.
1657   spdy_session_request1.reset();
1658   request_deleted_callback2.WaitUntilInvoked();
1659   request_deleted_callback3.WaitUntilInvoked();
1660   EXPECT_FALSE(request_deleted_callback1.invoked());
1661 
1662   // Nothing should happen when the third request is destroyed.
1663   spdy_session_request3.reset();
1664   base::RunLoop().RunUntilIdle();
1665   EXPECT_FALSE(request_deleted_callback1.invoked());
1666 }
1667 
TEST_F(SpdySessionPoolTest,RequestSessionDuringNotification)1668 TEST_F(SpdySessionPoolTest, RequestSessionDuringNotification) {
1669   const SpdySessionKey kSessionKey(
1670       HostPortPair("foo.test", 443), ProxyChain::Direct(),
1671       PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
1672       SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1673 
1674   CreateNetworkSession();
1675 
1676   // First request. Its request deleted callback should never be invoked.
1677   TestOnRequestDeletedCallback request_deleted_callback1;
1678   TestRequestDelegate request_delegate1;
1679   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request1;
1680   bool is_first_request_for_session;
1681   EXPECT_FALSE(spdy_session_pool_->RequestSession(
1682       kSessionKey, /* enable_ip_based_pooling = */ false,
1683       /* is_websocket = */ false, NetLogWithSource(),
1684       request_deleted_callback1.Callback(), &request_delegate1,
1685       &spdy_session_request1, &is_first_request_for_session));
1686   EXPECT_TRUE(is_first_request_for_session);
1687 
1688   // Second request.
1689   TestOnRequestDeletedCallback request_deleted_callback2;
1690   TestRequestDelegate request_delegate2;
1691   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request2;
1692   EXPECT_FALSE(spdy_session_pool_->RequestSession(
1693       kSessionKey, /* enable_ip_based_pooling = */ false,
1694       /* is_websocket = */ false, NetLogWithSource(),
1695       request_deleted_callback2.Callback(), &request_delegate2,
1696       &spdy_session_request2, &is_first_request_for_session));
1697   EXPECT_FALSE(is_first_request_for_session);
1698 
1699   TestOnRequestDeletedCallback request_deleted_callback3;
1700   TestRequestDelegate request_delegate3;
1701   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request3;
1702   TestOnRequestDeletedCallback request_deleted_callback4;
1703   TestRequestDelegate request_delegate4;
1704   std::unique_ptr<SpdySessionPool::SpdySessionRequest> spdy_session_request4;
1705   request_deleted_callback2.SetRequestDeletedCallback(
1706       base::BindLambdaForTesting([&]() {
1707         // Third request. It should again be marked as the first request for the
1708         // session, since it's only created after the original two have been
1709         // removed.
1710         bool is_first_request_for_session;
1711         EXPECT_FALSE(spdy_session_pool_->RequestSession(
1712             kSessionKey, /* enable_ip_based_pooling = */ false,
1713             /* is_websocket = */ false, NetLogWithSource(),
1714             request_deleted_callback3.Callback(), &request_delegate3,
1715             &spdy_session_request3, &is_first_request_for_session));
1716         EXPECT_TRUE(is_first_request_for_session);
1717 
1718         // Fourth request.
1719         EXPECT_FALSE(spdy_session_pool_->RequestSession(
1720             kSessionKey, /* enable_ip_based_pooling = */ false,
1721             /* is_websocket = */ false, NetLogWithSource(),
1722             request_deleted_callback4.Callback(), &request_delegate4,
1723             &spdy_session_request4, &is_first_request_for_session));
1724         EXPECT_FALSE(is_first_request_for_session);
1725       }));
1726 
1727   // Destroying the first request should cause the second callback to be
1728   // invoked, and the third and fourth request to be made.
1729   spdy_session_request1.reset();
1730   request_deleted_callback2.WaitUntilInvoked();
1731   base::RunLoop().RunUntilIdle();
1732   EXPECT_FALSE(request_deleted_callback1.invoked());
1733   EXPECT_FALSE(request_deleted_callback3.invoked());
1734   EXPECT_FALSE(request_deleted_callback4.invoked());
1735   EXPECT_TRUE(spdy_session_request3);
1736   EXPECT_TRUE(spdy_session_request4);
1737 
1738   // Destroying the third request should cause the fourth callback to be
1739   // invoked.
1740   spdy_session_request3.reset();
1741   request_deleted_callback4.WaitUntilInvoked();
1742   EXPECT_FALSE(request_deleted_callback1.invoked());
1743   EXPECT_FALSE(request_deleted_callback3.invoked());
1744 }
1745 
1746 static const char kSSLServerTestHost[] = "config-changed.test";
1747 
1748 static const struct {
1749   const char* url;
1750   const char* proxy_pac_string;
1751   bool expect_invalidated;
1752 } kSSLServerTests[] = {
1753     // If the host and port match, the session should be invalidated.
1754     {"https://config-changed.test", "DIRECT", true},
1755     // If host and port do not match, the session should not be invalidated.
1756     {"https://mail.config-changed.test", "DIRECT", false},
1757     {"https://config-changed.test:444", "DIRECT", false},
1758     // If the proxy matches, the session should be invalidated independent of
1759     // the host.
1760     {"https://config-changed.test", "HTTPS config-changed.test:443", true},
1761     {"https://mail.config-changed.test", "HTTPS config-changed.test:443", true},
1762     // HTTP and SOCKS proxies do not have client certificates.
1763     {"https://mail.config-changed.test", "PROXY config-changed.test:443",
1764      false},
1765     {"https://mail.config-changed.test", "SOCKS5 config-changed.test:443",
1766      false},
1767     // The proxy host and port must match.
1768     {"https://mail.config-changed.test", "HTTPS mail.config-changed.test:443",
1769      false},
1770     {"https://mail.config-changed.test", "HTTPS config-changed.test:444",
1771      false},
1772 };
1773 
1774 // Tests the OnSSLConfigForServersChanged() method matches SpdySessions as
1775 // expected.
TEST_F(SpdySessionPoolTest,SSLConfigForServerChanged)1776 TEST_F(SpdySessionPoolTest, SSLConfigForServerChanged) {
1777   const MockConnect connect_data(SYNCHRONOUS, OK);
1778   const MockRead reads[] = {
1779       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1780   };
1781 
1782   std::vector<std::unique_ptr<StaticSocketDataProvider>> socket_data;
1783   size_t num_tests = std::size(kSSLServerTests);
1784   for (size_t i = 0; i < num_tests; i++) {
1785     socket_data.push_back(std::make_unique<StaticSocketDataProvider>(
1786         reads, base::span<MockWrite>()));
1787     socket_data.back()->set_connect_data(connect_data);
1788     session_deps_.socket_factory->AddSocketDataProvider(
1789         socket_data.back().get());
1790     AddSSLSocketData();
1791   }
1792 
1793   CreateNetworkSession();
1794 
1795   std::vector<base::WeakPtr<SpdySession>> sessions;
1796   for (size_t i = 0; i < num_tests; i++) {
1797     SpdySessionKey key(
1798         HostPortPair::FromURL(GURL(kSSLServerTests[i].url)),
1799         PacResultElementToProxyChain(kSSLServerTests[i].proxy_pac_string),
1800         PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
1801         SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1802     sessions.push_back(
1803         CreateSpdySession(http_session_.get(), key, NetLogWithSource()));
1804   }
1805 
1806   // All sessions are available.
1807   for (size_t i = 0; i < num_tests; i++) {
1808     SCOPED_TRACE(i);
1809     EXPECT_TRUE(sessions[i]->IsAvailable());
1810   }
1811 
1812   spdy_session_pool_->OnSSLConfigForServersChanged(
1813       {HostPortPair(kSSLServerTestHost, 443)});
1814   base::RunLoop().RunUntilIdle();
1815 
1816   // Sessions were inactive, so the unavailable sessions are closed.
1817   for (size_t i = 0; i < num_tests; i++) {
1818     SCOPED_TRACE(i);
1819     if (kSSLServerTests[i].expect_invalidated) {
1820       EXPECT_FALSE(sessions[i]);
1821     } else {
1822       ASSERT_TRUE(sessions[i]);
1823       EXPECT_TRUE(sessions[i]->IsAvailable());
1824     }
1825   }
1826 }
1827 
1828 // Tests the OnSSLConfigForServersChanged() method matches SpdySessions
1829 // containing proxy chains.
TEST_F(SpdySessionPoolTest,SSLConfigForServerChangedWithProxyChain)1830 TEST_F(SpdySessionPoolTest, SSLConfigForServerChangedWithProxyChain) {
1831   const MockConnect connect_data(SYNCHRONOUS, OK);
1832   const MockRead reads[] = {
1833       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1834   };
1835 
1836   ProxyChain proxy_chain({
1837       ProxyServer::FromSchemeHostAndPort(ProxyServer::Scheme::SCHEME_HTTPS,
1838                                          "proxya", 443),
1839       ProxyServer::FromSchemeHostAndPort(ProxyServer::Scheme::SCHEME_HTTPS,
1840                                          "proxyb", 443),
1841       ProxyServer::FromSchemeHostAndPort(ProxyServer::Scheme::SCHEME_HTTPS,
1842                                          "proxyc", 443),
1843   });
1844 
1845   std::vector<std::unique_ptr<StaticSocketDataProvider>> socket_data;
1846   socket_data.push_back(std::make_unique<StaticSocketDataProvider>(
1847       reads, base::span<MockWrite>()));
1848   socket_data.back()->set_connect_data(connect_data);
1849   session_deps_.socket_factory->AddSocketDataProvider(socket_data.back().get());
1850   AddSSLSocketData();
1851 
1852   CreateNetworkSession();
1853 
1854   SpdySessionKey key(HostPortPair::FromURL(GURL("https://example.com")),
1855                      proxy_chain, PRIVACY_MODE_DISABLED,
1856                      SpdySessionKey::IsProxySession::kFalse, SocketTag(),
1857                      NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1858   base::WeakPtr<SpdySession> session =
1859       CreateSpdySession(http_session_.get(), key, NetLogWithSource());
1860 
1861   EXPECT_TRUE(session->IsAvailable());
1862 
1863   spdy_session_pool_->OnSSLConfigForServersChanged(
1864       {HostPortPair("proxyb", 443)});
1865   base::RunLoop().RunUntilIdle();
1866 
1867   // The unavailable session is closed.
1868   EXPECT_FALSE(session);
1869 }
1870 
1871 // Tests the OnSSLConfigForServersChanged() method when there are streams open.
TEST_F(SpdySessionPoolTest,SSLConfigForServerChangedWithStreams)1872 TEST_F(SpdySessionPoolTest, SSLConfigForServerChangedWithStreams) {
1873   // Set up a SpdySession with an active, created, and pending stream.
1874   SpdyTestUtil spdy_util;
1875   spdy::SettingsMap settings;
1876   settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = 2;
1877   spdy::SpdySerializedFrame settings_frame =
1878       spdy_util.ConstructSpdySettings(settings);
1879   spdy::SpdySerializedFrame settings_ack = spdy_util.ConstructSpdySettingsAck();
1880   spdy::SpdySerializedFrame req(
1881       spdy_util.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
1882 
1883   const MockConnect connect_data(SYNCHRONOUS, OK);
1884   const MockRead reads[] = {
1885       CreateMockRead(settings_frame),
1886       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1887   };
1888   const MockWrite writes[] = {
1889       CreateMockWrite(settings_ack),
1890       CreateMockWrite(req),
1891   };
1892 
1893   StaticSocketDataProvider socket_data(reads, writes);
1894   socket_data.set_connect_data(connect_data);
1895   session_deps_.socket_factory->AddSocketDataProvider(&socket_data);
1896   AddSSLSocketData();
1897 
1898   CreateNetworkSession();
1899 
1900   const GURL url(kDefaultUrl);
1901   SpdySessionKey key(HostPortPair::FromURL(url), ProxyChain::Direct(),
1902                      PRIVACY_MODE_DISABLED,
1903                      SpdySessionKey::IsProxySession::kFalse, SocketTag(),
1904                      NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
1905   base::WeakPtr<SpdySession> session =
1906       CreateSpdySession(http_session_.get(), key, NetLogWithSource());
1907 
1908   // Pick up the SETTINGS frame to update SETTINGS_MAX_CONCURRENT_STREAMS.
1909   base::RunLoop().RunUntilIdle();
1910   EXPECT_EQ(2u, max_concurrent_streams(session));
1911 
1912   // The first two stream requests should succeed.
1913   base::WeakPtr<SpdyStream> active_stream = CreateStreamSynchronously(
1914       SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, NetLogWithSource());
1915   test::StreamDelegateDoNothing active_stream_delegate(active_stream);
1916   active_stream->SetDelegate(&active_stream_delegate);
1917   base::WeakPtr<SpdyStream> created_stream = CreateStreamSynchronously(
1918       SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, NetLogWithSource());
1919   test::StreamDelegateDoNothing created_stream_delegate(created_stream);
1920   created_stream->SetDelegate(&created_stream_delegate);
1921 
1922   // The third will block.
1923   TestCompletionCallback callback;
1924   SpdyStreamRequest stream_request;
1925   EXPECT_THAT(
1926       stream_request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session, url,
1927                                   /*can_send_early=*/false, MEDIUM, SocketTag(),
1928                                   NetLogWithSource(), callback.callback(),
1929                                   TRAFFIC_ANNOTATION_FOR_TESTS),
1930       IsError(ERR_IO_PENDING));
1931 
1932   // Activate the first stream by sending data.
1933   spdy::Http2HeaderBlock headers(spdy_util.ConstructGetHeaderBlock(url.spec()));
1934   active_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
1935   base::RunLoop().RunUntilIdle();
1936 
1937   // The active stream should now have a stream ID.
1938   EXPECT_EQ(1u, active_stream->stream_id());
1939   EXPECT_EQ(spdy::kInvalidStreamId, created_stream->stream_id());
1940   EXPECT_TRUE(session->is_active());
1941   EXPECT_TRUE(session->IsAvailable());
1942 
1943   spdy_session_pool_->OnSSLConfigForServersChanged(
1944       {HostPortPair::FromURL(url)});
1945   base::RunLoop().RunUntilIdle();
1946 
1947   // The active stream is still alive, so the session is still active.
1948   ASSERT_TRUE(session);
1949   EXPECT_TRUE(session->is_active());
1950   ASSERT_TRUE(active_stream);
1951 
1952   // The session is no longer available.
1953   EXPECT_FALSE(session->IsAvailable());
1954   EXPECT_TRUE(session->IsGoingAway());
1955 
1956   // The pending and created stream are cancelled.
1957   // TODO(https://crbug.com/1213609): Ideally, this would be recoverable.
1958   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NETWORK_CHANGED));
1959   EXPECT_THAT(created_stream_delegate.WaitForClose(),
1960               IsError(ERR_NETWORK_CHANGED));
1961 
1962   // Close the active stream.
1963   active_stream->Close();
1964   // TODO(https://crbug.com/982499): The invalidated session should be closed
1965   // after a RunUntilIdle(), but it is not.
1966 }
1967 
1968 // Tests the OnSSLConfigForServersChanged() method when there only pending
1969 // streams active.
TEST_F(SpdySessionPoolTest,SSLConfigForServerChangedWithOnlyPendingStreams)1970 TEST_F(SpdySessionPoolTest, SSLConfigForServerChangedWithOnlyPendingStreams) {
1971   // Set up a SpdySession that accepts no streams.
1972   SpdyTestUtil spdy_util;
1973   spdy::SettingsMap settings;
1974   settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = 0;
1975   spdy::SpdySerializedFrame settings_frame =
1976       spdy_util.ConstructSpdySettings(settings);
1977   spdy::SpdySerializedFrame settings_ack = spdy_util.ConstructSpdySettingsAck();
1978 
1979   const MockConnect connect_data(SYNCHRONOUS, OK);
1980   const MockRead reads[] = {
1981       CreateMockRead(settings_frame),
1982       MockRead(SYNCHRONOUS, ERR_IO_PENDING)  // Stall forever.
1983   };
1984   const MockWrite writes[] = {
1985       CreateMockWrite(settings_ack),
1986   };
1987 
1988   StaticSocketDataProvider socket_data(reads, writes);
1989   socket_data.set_connect_data(connect_data);
1990   session_deps_.socket_factory->AddSocketDataProvider(&socket_data);
1991   AddSSLSocketData();
1992 
1993   CreateNetworkSession();
1994 
1995   const GURL url(kDefaultUrl);
1996   SpdySessionKey key(HostPortPair::FromURL(url), ProxyChain::Direct(),
1997                      PRIVACY_MODE_DISABLED,
1998                      SpdySessionKey::IsProxySession::kFalse, SocketTag(),
1999                      NetworkAnonymizationKey(), SecureDnsPolicy::kAllow);
2000   base::WeakPtr<SpdySession> session =
2001       CreateSpdySession(http_session_.get(), key, NetLogWithSource());
2002 
2003   // Pick up the SETTINGS frame to update SETTINGS_MAX_CONCURRENT_STREAMS.
2004   base::RunLoop().RunUntilIdle();
2005   EXPECT_EQ(0u, max_concurrent_streams(session));
2006 
2007   // Create a stream. It should block on the stream limit.
2008   TestCompletionCallback callback;
2009   SpdyStreamRequest stream_request;
2010   ASSERT_THAT(
2011       stream_request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session, url,
2012                                   /*can_send_early=*/false, MEDIUM, SocketTag(),
2013                                   NetLogWithSource(), callback.callback(),
2014                                   TRAFFIC_ANNOTATION_FOR_TESTS),
2015       IsError(ERR_IO_PENDING));
2016 
2017   spdy_session_pool_->OnSSLConfigForServersChanged(
2018       {HostPortPair::FromURL(url)});
2019   base::RunLoop().RunUntilIdle();
2020 
2021   // The pending stream is cancelled.
2022   // TODO(https://crbug.com/1213609): Ideally, this would be recoverable.
2023   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NETWORK_CHANGED));
2024   EXPECT_FALSE(session);
2025 }
2026 
2027 }  // namespace net
2028