| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_stream_factory_impl.h" | 5 #include "net/http/http_stream_factory_impl.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "net/base/port_util.h" | 14 #include "net/base/port_util.h" |
| 15 #include "net/base/test_completion_callback.h" | 15 #include "net/base/test_completion_callback.h" |
| 16 #include "net/cert/mock_cert_verifier.h" | 16 #include "net/cert/mock_cert_verifier.h" |
| 17 #include "net/dns/mock_host_resolver.h" | 17 #include "net/dns/mock_host_resolver.h" |
| 18 #include "net/http/bidirectional_stream_job.h" |
| 18 #include "net/http/http_auth_handler_factory.h" | 19 #include "net/http/http_auth_handler_factory.h" |
| 19 #include "net/http/http_network_session.h" | 20 #include "net/http/http_network_session.h" |
| 20 #include "net/http/http_network_session_peer.h" | 21 #include "net/http/http_network_session_peer.h" |
| 21 #include "net/http/http_network_transaction.h" | 22 #include "net/http/http_network_transaction.h" |
| 22 #include "net/http/http_request_info.h" | 23 #include "net/http/http_request_info.h" |
| 23 #include "net/http/http_server_properties.h" | 24 #include "net/http/http_server_properties.h" |
| 24 #include "net/http/http_server_properties_impl.h" | 25 #include "net/http/http_server_properties_impl.h" |
| 25 #include "net/http/http_stream.h" | 26 #include "net/http/http_stream.h" |
| 26 #include "net/http/transport_security_state.h" | 27 #include "net/http/transport_security_state.h" |
| 27 #include "net/log/net_log.h" | 28 #include "net/log/net_log.h" |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 return scoped_ptr<WebSocketStream>(); | 107 return scoped_ptr<WebSocketStream>(); |
| 107 } | 108 } |
| 108 | 109 |
| 109 private: | 110 private: |
| 110 const StreamType type_; | 111 const StreamType type_; |
| 111 }; | 112 }; |
| 112 | 113 |
| 113 // HttpStreamFactoryImpl subclass that can wait until a preconnect is complete. | 114 // HttpStreamFactoryImpl subclass that can wait until a preconnect is complete. |
| 114 class MockHttpStreamFactoryImplForPreconnect : public HttpStreamFactoryImpl { | 115 class MockHttpStreamFactoryImplForPreconnect : public HttpStreamFactoryImpl { |
| 115 public: | 116 public: |
| 116 MockHttpStreamFactoryImplForPreconnect(HttpNetworkSession* session, | 117 MockHttpStreamFactoryImplForPreconnect(HttpNetworkSession* session) |
| 117 bool for_websockets) | 118 : HttpStreamFactoryImpl(session, false), |
| 118 : HttpStreamFactoryImpl(session, for_websockets), | |
| 119 preconnect_done_(false), | 119 preconnect_done_(false), |
| 120 waiting_for_preconnect_(false) {} | 120 waiting_for_preconnect_(false) {} |
| 121 | 121 |
| 122 void WaitForPreconnects() { | 122 void WaitForPreconnects() { |
| 123 while (!preconnect_done_) { | 123 while (!preconnect_done_) { |
| 124 waiting_for_preconnect_ = true; | 124 waiting_for_preconnect_ = true; |
| 125 base::MessageLoop::current()->Run(); | 125 base::MessageLoop::current()->Run(); |
| 126 waiting_for_preconnect_ = false; | 126 waiting_for_preconnect_ = false; |
| 127 } | 127 } |
| 128 } | 128 } |
| 129 | 129 |
| 130 private: | 130 private: |
| 131 // HttpStreamFactoryImpl methods. | 131 // HttpStreamFactoryImpl methods. |
| 132 void OnPreconnectsCompleteInternal() override { | 132 void OnPreconnectsCompleteInternal() override { |
| 133 preconnect_done_ = true; | 133 preconnect_done_ = true; |
| 134 if (waiting_for_preconnect_) | 134 if (waiting_for_preconnect_) |
| 135 base::MessageLoop::current()->QuitWhenIdle(); | 135 base::MessageLoop::current()->QuitWhenIdle(); |
| 136 } | 136 } |
| 137 | 137 |
| 138 bool preconnect_done_; | 138 bool preconnect_done_; |
| 139 bool waiting_for_preconnect_; | 139 bool waiting_for_preconnect_; |
| 140 }; | 140 }; |
| 141 | 141 |
| 142 class StreamRequestWaiter : public HttpStreamRequest::Delegate { | 142 class StreamRequestWaiter : public HttpStreamRequest::Delegate { |
| 143 public: | 143 public: |
| 144 StreamRequestWaiter() | 144 StreamRequestWaiter() |
| 145 : waiting_for_stream_(false), | 145 : waiting_for_stream_(false), stream_done_(false), error_status_(OK) {} |
| 146 stream_done_(false) {} | |
| 147 | 146 |
| 148 // HttpStreamRequest::Delegate | 147 // HttpStreamRequest::Delegate |
| 149 | 148 |
| 150 void OnStreamReady(const SSLConfig& used_ssl_config, | 149 void OnStreamReady(const SSLConfig& used_ssl_config, |
| 151 const ProxyInfo& used_proxy_info, | 150 const ProxyInfo& used_proxy_info, |
| 152 HttpStream* stream) override { | 151 HttpStream* stream) override { |
| 153 stream_done_ = true; | 152 stream_done_ = true; |
| 154 if (waiting_for_stream_) | 153 if (waiting_for_stream_) |
| 155 base::MessageLoop::current()->QuitWhenIdle(); | 154 base::MessageLoop::current()->QuitWhenIdle(); |
| 156 stream_.reset(stream); | 155 stream_.reset(stream); |
| 157 used_ssl_config_ = used_ssl_config; | 156 used_ssl_config_ = used_ssl_config; |
| 158 used_proxy_info_ = used_proxy_info; | 157 used_proxy_info_ = used_proxy_info; |
| 159 } | 158 } |
| 160 | 159 |
| 161 void OnWebSocketHandshakeStreamReady( | 160 void OnWebSocketHandshakeStreamReady( |
| 162 const SSLConfig& used_ssl_config, | 161 const SSLConfig& used_ssl_config, |
| 163 const ProxyInfo& used_proxy_info, | 162 const ProxyInfo& used_proxy_info, |
| 164 WebSocketHandshakeStreamBase* stream) override { | 163 WebSocketHandshakeStreamBase* stream) override { |
| 165 stream_done_ = true; | 164 stream_done_ = true; |
| 166 if (waiting_for_stream_) | 165 if (waiting_for_stream_) |
| 167 base::MessageLoop::current()->QuitWhenIdle(); | 166 base::MessageLoop::current()->QuitWhenIdle(); |
| 168 websocket_stream_.reset(stream); | 167 websocket_stream_.reset(stream); |
| 169 used_ssl_config_ = used_ssl_config; | 168 used_ssl_config_ = used_ssl_config; |
| 170 used_proxy_info_ = used_proxy_info; | 169 used_proxy_info_ = used_proxy_info; |
| 171 } | 170 } |
| 172 | 171 |
| 172 void OnBidirectionalStreamJobReady(const SSLConfig& used_ssl_config, |
| 173 const ProxyInfo& used_proxy_info, |
| 174 BidirectionalStreamJob* stream) override { |
| 175 stream_done_ = true; |
| 176 if (waiting_for_stream_) |
| 177 base::MessageLoop::current()->QuitWhenIdle(); |
| 178 bidirectional_stream_job_.reset(stream); |
| 179 used_ssl_config_ = used_ssl_config; |
| 180 used_proxy_info_ = used_proxy_info; |
| 181 } |
| 182 |
| 173 void OnStreamFailed(int status, | 183 void OnStreamFailed(int status, |
| 174 const SSLConfig& used_ssl_config, | 184 const SSLConfig& used_ssl_config, |
| 175 SSLFailureState ssl_failure_state) override {} | 185 SSLFailureState ssl_failure_state) override { |
| 186 stream_done_ = true; |
| 187 if (waiting_for_stream_) |
| 188 base::MessageLoop::current()->QuitWhenIdle(); |
| 189 used_ssl_config_ = used_ssl_config; |
| 190 error_status_ = status; |
| 191 } |
| 176 | 192 |
| 177 void OnCertificateError(int status, | 193 void OnCertificateError(int status, |
| 178 const SSLConfig& used_ssl_config, | 194 const SSLConfig& used_ssl_config, |
| 179 const SSLInfo& ssl_info) override {} | 195 const SSLInfo& ssl_info) override {} |
| 180 | 196 |
| 181 void OnNeedsProxyAuth(const HttpResponseInfo& proxy_response, | 197 void OnNeedsProxyAuth(const HttpResponseInfo& proxy_response, |
| 182 const SSLConfig& used_ssl_config, | 198 const SSLConfig& used_ssl_config, |
| 183 const ProxyInfo& used_proxy_info, | 199 const ProxyInfo& used_proxy_info, |
| 184 HttpAuthController* auth_controller) override {} | 200 HttpAuthController* auth_controller) override {} |
| 185 | 201 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 210 } | 226 } |
| 211 | 227 |
| 212 HttpStream* stream() { | 228 HttpStream* stream() { |
| 213 return stream_.get(); | 229 return stream_.get(); |
| 214 } | 230 } |
| 215 | 231 |
| 216 MockWebSocketHandshakeStream* websocket_stream() { | 232 MockWebSocketHandshakeStream* websocket_stream() { |
| 217 return static_cast<MockWebSocketHandshakeStream*>(websocket_stream_.get()); | 233 return static_cast<MockWebSocketHandshakeStream*>(websocket_stream_.get()); |
| 218 } | 234 } |
| 219 | 235 |
| 236 BidirectionalStreamJob* bidirectional_stream_job() { |
| 237 return bidirectional_stream_job_.get(); |
| 238 } |
| 239 |
| 220 bool stream_done() const { return stream_done_; } | 240 bool stream_done() const { return stream_done_; } |
| 241 int error_status() const { return error_status_; } |
| 221 | 242 |
| 222 private: | 243 private: |
| 223 bool waiting_for_stream_; | 244 bool waiting_for_stream_; |
| 224 bool stream_done_; | 245 bool stream_done_; |
| 225 scoped_ptr<HttpStream> stream_; | 246 scoped_ptr<HttpStream> stream_; |
| 226 scoped_ptr<WebSocketHandshakeStreamBase> websocket_stream_; | 247 scoped_ptr<WebSocketHandshakeStreamBase> websocket_stream_; |
| 248 scoped_ptr<BidirectionalStreamJob> bidirectional_stream_job_; |
| 227 SSLConfig used_ssl_config_; | 249 SSLConfig used_ssl_config_; |
| 228 ProxyInfo used_proxy_info_; | 250 ProxyInfo used_proxy_info_; |
| 251 int error_status_; |
| 229 | 252 |
| 230 DISALLOW_COPY_AND_ASSIGN(StreamRequestWaiter); | 253 DISALLOW_COPY_AND_ASSIGN(StreamRequestWaiter); |
| 231 }; | 254 }; |
| 232 | 255 |
| 233 class WebSocketSpdyHandshakeStream : public MockWebSocketHandshakeStream { | 256 class WebSocketSpdyHandshakeStream : public MockWebSocketHandshakeStream { |
| 234 public: | 257 public: |
| 235 explicit WebSocketSpdyHandshakeStream( | 258 explicit WebSocketSpdyHandshakeStream( |
| 236 const base::WeakPtr<SpdySession>& spdy_session) | 259 const base::WeakPtr<SpdySession>& spdy_session) |
| 237 : MockWebSocketHandshakeStream(kStreamTypeSpdy), | 260 : MockWebSocketHandshakeStream(kStreamTypeSpdy), |
| 238 spdy_session_(spdy_session) {} | 261 spdy_session_(spdy_session) {} |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 { 2, false }, | 313 { 2, false }, |
| 291 { 1, true}, | 314 { 1, true}, |
| 292 { 2, true}, | 315 { 2, true}, |
| 293 }; | 316 }; |
| 294 | 317 |
| 295 void PreconnectHelperForURL(int num_streams, | 318 void PreconnectHelperForURL(int num_streams, |
| 296 const GURL& url, | 319 const GURL& url, |
| 297 HttpNetworkSession* session) { | 320 HttpNetworkSession* session) { |
| 298 HttpNetworkSessionPeer peer(session); | 321 HttpNetworkSessionPeer peer(session); |
| 299 MockHttpStreamFactoryImplForPreconnect* mock_factory = | 322 MockHttpStreamFactoryImplForPreconnect* mock_factory = |
| 300 new MockHttpStreamFactoryImplForPreconnect(session, false); | 323 new MockHttpStreamFactoryImplForPreconnect(session); |
| 301 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(mock_factory)); | 324 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(mock_factory)); |
| 302 SSLConfig ssl_config; | 325 SSLConfig ssl_config; |
| 303 session->ssl_config_service()->GetSSLConfig(&ssl_config); | 326 session->ssl_config_service()->GetSSLConfig(&ssl_config); |
| 304 | 327 |
| 305 HttpRequestInfo request; | 328 HttpRequestInfo request; |
| 306 request.method = "GET"; | 329 request.method = "GET"; |
| 307 request.url = url; | 330 request.url = url; |
| 308 request.load_flags = 0; | 331 request.load_flags = 0; |
| 309 | 332 |
| 310 session->http_stream_factory()->PreconnectStreams(num_streams, request, | 333 session->http_stream_factory()->PreconnectStreams(num_streams, request, |
| (...skipping 1030 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1341 EXPECT_EQ(1, GetSocketPoolGroupCount( | 1364 EXPECT_EQ(1, GetSocketPoolGroupCount( |
| 1342 session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | 1365 session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); |
| 1343 EXPECT_EQ(0, GetSocketPoolGroupCount( | 1366 EXPECT_EQ(0, GetSocketPoolGroupCount( |
| 1344 session->GetTransportSocketPool( | 1367 session->GetTransportSocketPool( |
| 1345 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | 1368 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); |
| 1346 EXPECT_EQ(0, GetSocketPoolGroupCount( | 1369 EXPECT_EQ(0, GetSocketPoolGroupCount( |
| 1347 session->GetSSLSocketPool(HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | 1370 session->GetSSLSocketPool(HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); |
| 1348 EXPECT_TRUE(waiter.used_proxy_info().is_direct()); | 1371 EXPECT_TRUE(waiter.used_proxy_info().is_direct()); |
| 1349 } | 1372 } |
| 1350 | 1373 |
| 1374 #if defined(ENABLE_BIDIRECTIONAL_STREAM) |
| 1375 TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamJob) { |
| 1376 SpdySessionDependencies session_deps(GetParam(), |
| 1377 ProxyService::CreateDirect()); |
| 1378 |
| 1379 MockRead mock_read(ASYNC, OK); |
| 1380 SequencedSocketData socket_data(&mock_read, 1, nullptr, 0); |
| 1381 socket_data.set_connect_data(MockConnect(ASYNC, OK)); |
| 1382 session_deps.socket_factory->AddSocketDataProvider(&socket_data); |
| 1383 |
| 1384 SSLSocketDataProvider ssl_socket_data(ASYNC, OK); |
| 1385 ssl_socket_data.SetNextProto(GetParam()); |
| 1386 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data); |
| 1387 |
| 1388 HostPortPair host_port_pair("www.google.com", 443); |
| 1389 scoped_ptr<HttpNetworkSession> session( |
| 1390 SpdySessionDependencies::SpdyCreateSession(&session_deps)); |
| 1391 |
| 1392 // Now request a stream. |
| 1393 HttpRequestInfo request_info; |
| 1394 request_info.method = "GET"; |
| 1395 request_info.url = GURL("https://www.google.com"); |
| 1396 request_info.load_flags = 0; |
| 1397 |
| 1398 SSLConfig ssl_config; |
| 1399 StreamRequestWaiter waiter; |
| 1400 scoped_ptr<HttpStreamRequest> request( |
| 1401 session->http_stream_factory()->RequestBidirectionalStreamJob( |
| 1402 request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter, |
| 1403 BoundNetLog())); |
| 1404 waiter.WaitForStream(); |
| 1405 EXPECT_TRUE(waiter.stream_done()); |
| 1406 EXPECT_FALSE(waiter.websocket_stream()); |
| 1407 ASSERT_FALSE(waiter.stream()); |
| 1408 ASSERT_TRUE(waiter.bidirectional_stream_job()); |
| 1409 EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetTransportSocketPool( |
| 1410 HttpNetworkSession::NORMAL_SOCKET_POOL))); |
| 1411 EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSSLSocketPool( |
| 1412 HttpNetworkSession::NORMAL_SOCKET_POOL))); |
| 1413 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetTransportSocketPool( |
| 1414 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); |
| 1415 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSSLSocketPool( |
| 1416 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); |
| 1417 EXPECT_TRUE(waiter.used_proxy_info().is_direct()); |
| 1418 ASSERT_EQ(0u, |
| 1419 static_cast<HttpStreamFactoryImpl*>(session->http_stream_factory()) |
| 1420 ->num_orphaned_jobs()); |
| 1421 } |
| 1422 |
| 1423 TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamJobFailure) { |
| 1424 SpdySessionDependencies session_deps(GetParam(), |
| 1425 ProxyService::CreateDirect()); |
| 1426 |
| 1427 MockRead mock_read(ASYNC, OK); |
| 1428 SequencedSocketData socket_data(&mock_read, 1, nullptr, 0); |
| 1429 socket_data.set_connect_data(MockConnect(ASYNC, OK)); |
| 1430 session_deps.socket_factory->AddSocketDataProvider(&socket_data); |
| 1431 |
| 1432 SSLSocketDataProvider ssl_socket_data(ASYNC, OK); |
| 1433 |
| 1434 // If HTTP/1 is used, BidirectionalStreamJob should not be obtained. |
| 1435 ssl_socket_data.SetNextProto(kProtoHTTP11); |
| 1436 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data); |
| 1437 |
| 1438 HostPortPair host_port_pair("www.google.com", 443); |
| 1439 scoped_ptr<HttpNetworkSession> session( |
| 1440 SpdySessionDependencies::SpdyCreateSession(&session_deps)); |
| 1441 |
| 1442 // Now request a stream. |
| 1443 HttpRequestInfo request_info; |
| 1444 request_info.method = "GET"; |
| 1445 request_info.url = GURL("https://www.google.com"); |
| 1446 request_info.load_flags = 0; |
| 1447 |
| 1448 SSLConfig ssl_config; |
| 1449 StreamRequestWaiter waiter; |
| 1450 scoped_ptr<HttpStreamRequest> request( |
| 1451 session->http_stream_factory()->RequestBidirectionalStreamJob( |
| 1452 request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter, |
| 1453 BoundNetLog())); |
| 1454 waiter.WaitForStream(); |
| 1455 EXPECT_TRUE(waiter.stream_done()); |
| 1456 ASSERT_EQ(ERR_FAILED, waiter.error_status()); |
| 1457 EXPECT_FALSE(waiter.websocket_stream()); |
| 1458 ASSERT_FALSE(waiter.stream()); |
| 1459 ASSERT_FALSE(waiter.bidirectional_stream_job()); |
| 1460 EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetTransportSocketPool( |
| 1461 HttpNetworkSession::NORMAL_SOCKET_POOL))); |
| 1462 EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSSLSocketPool( |
| 1463 HttpNetworkSession::NORMAL_SOCKET_POOL))); |
| 1464 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetTransportSocketPool( |
| 1465 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); |
| 1466 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSSLSocketPool( |
| 1467 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); |
| 1468 ASSERT_EQ(0u, |
| 1469 static_cast<HttpStreamFactoryImpl*>(session->http_stream_factory()) |
| 1470 ->num_orphaned_jobs()); |
| 1471 } |
| 1472 #endif |
| 1473 |
| 1351 // TODO(ricea): This test can be removed once the new WebSocket stack supports | 1474 // TODO(ricea): This test can be removed once the new WebSocket stack supports |
| 1352 // SPDY. Currently, even if we connect to a SPDY-supporting server, we need to | 1475 // SPDY. Currently, even if we connect to a SPDY-supporting server, we need to |
| 1353 // use plain SSL. | 1476 // use plain SSL. |
| 1354 TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyHandshakeStreamButGetSSL) { | 1477 TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyHandshakeStreamButGetSSL) { |
| 1355 SpdySessionDependencies session_deps(GetParam(), | 1478 SpdySessionDependencies session_deps(GetParam(), |
| 1356 ProxyService::CreateDirect()); | 1479 ProxyService::CreateDirect()); |
| 1357 | 1480 |
| 1358 MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING); | 1481 MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING); |
| 1359 StaticSocketDataProvider socket_data(&mock_read, 1, nullptr, 0); | 1482 StaticSocketDataProvider socket_data(&mock_read, 1, nullptr, 0); |
| 1360 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | 1483 socket_data.set_connect_data(MockConnect(ASYNC, OK)); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 EXPECT_TRUE(waiter.used_proxy_info().is_direct()); | 1668 EXPECT_TRUE(waiter.used_proxy_info().is_direct()); |
| 1546 | 1669 |
| 1547 // Make sure there is no orphaned job. it is already canceled. | 1670 // Make sure there is no orphaned job. it is already canceled. |
| 1548 ASSERT_EQ(0u, static_cast<HttpStreamFactoryImpl*>( | 1671 ASSERT_EQ(0u, static_cast<HttpStreamFactoryImpl*>( |
| 1549 session->http_stream_factory_for_websocket())->num_orphaned_jobs()); | 1672 session->http_stream_factory_for_websocket())->num_orphaned_jobs()); |
| 1550 } | 1673 } |
| 1551 | 1674 |
| 1552 } // namespace | 1675 } // namespace |
| 1553 | 1676 |
| 1554 } // namespace net | 1677 } // namespace net |
| OLD | NEW |