| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/http/http_stream_factory_impl.h" | |
| 6 | |
| 7 #include <string> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/basictypes.h" | |
| 11 #include "base/compiler_specific.h" | |
| 12 #include "net/base/net_log.h" | |
| 13 #include "net/base/test_completion_callback.h" | |
| 14 #include "net/cert/mock_cert_verifier.h" | |
| 15 #include "net/dns/mock_host_resolver.h" | |
| 16 #include "net/http/http_auth_handler_factory.h" | |
| 17 #include "net/http/http_network_session.h" | |
| 18 #include "net/http/http_network_session_peer.h" | |
| 19 #include "net/http/http_network_transaction.h" | |
| 20 #include "net/http/http_request_info.h" | |
| 21 #include "net/http/http_server_properties.h" | |
| 22 #include "net/http/http_server_properties_impl.h" | |
| 23 #include "net/http/http_stream.h" | |
| 24 #include "net/http/transport_security_state.h" | |
| 25 #include "net/proxy/proxy_info.h" | |
| 26 #include "net/proxy/proxy_service.h" | |
| 27 #include "net/socket/client_socket_handle.h" | |
| 28 #include "net/socket/mock_client_socket_pool_manager.h" | |
| 29 #include "net/socket/next_proto.h" | |
| 30 #include "net/socket/socket_test_util.h" | |
| 31 #include "net/spdy/spdy_session.h" | |
| 32 #include "net/spdy/spdy_session_pool.h" | |
| 33 #include "net/spdy/spdy_test_util_common.h" | |
| 34 #include "net/ssl/ssl_config_service.h" | |
| 35 #include "net/ssl/ssl_config_service_defaults.h" | |
| 36 // This file can be included from net/http even though | |
| 37 // it is in net/websockets because it doesn't | |
| 38 // introduce any link dependency to net/websockets. | |
| 39 #include "net/websockets/websocket_handshake_stream_base.h" | |
| 40 #include "testing/gtest/include/gtest/gtest.h" | |
| 41 | |
| 42 namespace net { | |
| 43 | |
| 44 namespace { | |
| 45 | |
| 46 class MockWebSocketHandshakeStream : public WebSocketHandshakeStreamBase { | |
| 47 public: | |
| 48 enum StreamType { | |
| 49 kStreamTypeBasic, | |
| 50 kStreamTypeSpdy, | |
| 51 }; | |
| 52 | |
| 53 explicit MockWebSocketHandshakeStream(StreamType type) : type_(type) {} | |
| 54 | |
| 55 ~MockWebSocketHandshakeStream() override {} | |
| 56 | |
| 57 StreamType type() const { | |
| 58 return type_; | |
| 59 } | |
| 60 | |
| 61 // HttpStream methods | |
| 62 int InitializeStream(const HttpRequestInfo* request_info, | |
| 63 RequestPriority priority, | |
| 64 const BoundNetLog& net_log, | |
| 65 const CompletionCallback& callback) override { | |
| 66 return ERR_IO_PENDING; | |
| 67 } | |
| 68 int SendRequest(const HttpRequestHeaders& request_headers, | |
| 69 HttpResponseInfo* response, | |
| 70 const CompletionCallback& callback) override { | |
| 71 return ERR_IO_PENDING; | |
| 72 } | |
| 73 int ReadResponseHeaders(const CompletionCallback& callback) override { | |
| 74 return ERR_IO_PENDING; | |
| 75 } | |
| 76 int ReadResponseBody(IOBuffer* buf, | |
| 77 int buf_len, | |
| 78 const CompletionCallback& callback) override { | |
| 79 return ERR_IO_PENDING; | |
| 80 } | |
| 81 void Close(bool not_reusable) override {} | |
| 82 bool IsResponseBodyComplete() const override { return false; } | |
| 83 bool CanFindEndOfResponse() const override { return false; } | |
| 84 bool IsConnectionReused() const override { return false; } | |
| 85 void SetConnectionReused() override {} | |
| 86 bool IsConnectionReusable() const override { return false; } | |
| 87 int64 GetTotalReceivedBytes() const override { return 0; } | |
| 88 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override { | |
| 89 return false; | |
| 90 } | |
| 91 void GetSSLInfo(SSLInfo* ssl_info) override {} | |
| 92 void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {} | |
| 93 bool IsSpdyHttpStream() const override { return false; } | |
| 94 void Drain(HttpNetworkSession* session) override {} | |
| 95 void SetPriority(RequestPriority priority) override {} | |
| 96 UploadProgress GetUploadProgress() const override { return UploadProgress(); } | |
| 97 HttpStream* RenewStreamForAuth() override { return nullptr; } | |
| 98 | |
| 99 scoped_ptr<WebSocketStream> Upgrade() override { | |
| 100 return scoped_ptr<WebSocketStream>(); | |
| 101 } | |
| 102 | |
| 103 private: | |
| 104 const StreamType type_; | |
| 105 }; | |
| 106 | |
| 107 // HttpStreamFactoryImpl subclass that can wait until a preconnect is complete. | |
| 108 class MockHttpStreamFactoryImplForPreconnect : public HttpStreamFactoryImpl { | |
| 109 public: | |
| 110 MockHttpStreamFactoryImplForPreconnect(HttpNetworkSession* session, | |
| 111 bool for_websockets) | |
| 112 : HttpStreamFactoryImpl(session, for_websockets), | |
| 113 preconnect_done_(false), | |
| 114 waiting_for_preconnect_(false) {} | |
| 115 | |
| 116 | |
| 117 void WaitForPreconnects() { | |
| 118 while (!preconnect_done_) { | |
| 119 waiting_for_preconnect_ = true; | |
| 120 base::MessageLoop::current()->Run(); | |
| 121 waiting_for_preconnect_ = false; | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 private: | |
| 126 // HttpStreamFactoryImpl methods. | |
| 127 void OnPreconnectsCompleteInternal() override { | |
| 128 preconnect_done_ = true; | |
| 129 if (waiting_for_preconnect_) | |
| 130 base::MessageLoop::current()->Quit(); | |
| 131 } | |
| 132 | |
| 133 bool preconnect_done_; | |
| 134 bool waiting_for_preconnect_; | |
| 135 }; | |
| 136 | |
| 137 class StreamRequestWaiter : public HttpStreamRequest::Delegate { | |
| 138 public: | |
| 139 StreamRequestWaiter() | |
| 140 : waiting_for_stream_(false), | |
| 141 stream_done_(false) {} | |
| 142 | |
| 143 // HttpStreamRequest::Delegate | |
| 144 | |
| 145 void OnStreamReady(const SSLConfig& used_ssl_config, | |
| 146 const ProxyInfo& used_proxy_info, | |
| 147 HttpStream* stream) override { | |
| 148 stream_done_ = true; | |
| 149 if (waiting_for_stream_) | |
| 150 base::MessageLoop::current()->Quit(); | |
| 151 stream_.reset(stream); | |
| 152 used_ssl_config_ = used_ssl_config; | |
| 153 used_proxy_info_ = used_proxy_info; | |
| 154 } | |
| 155 | |
| 156 void OnWebSocketHandshakeStreamReady( | |
| 157 const SSLConfig& used_ssl_config, | |
| 158 const ProxyInfo& used_proxy_info, | |
| 159 WebSocketHandshakeStreamBase* stream) override { | |
| 160 stream_done_ = true; | |
| 161 if (waiting_for_stream_) | |
| 162 base::MessageLoop::current()->Quit(); | |
| 163 websocket_stream_.reset(stream); | |
| 164 used_ssl_config_ = used_ssl_config; | |
| 165 used_proxy_info_ = used_proxy_info; | |
| 166 } | |
| 167 | |
| 168 void OnStreamFailed(int status, const SSLConfig& used_ssl_config) override {} | |
| 169 | |
| 170 void OnCertificateError(int status, | |
| 171 const SSLConfig& used_ssl_config, | |
| 172 const SSLInfo& ssl_info) override {} | |
| 173 | |
| 174 void OnNeedsProxyAuth(const HttpResponseInfo& proxy_response, | |
| 175 const SSLConfig& used_ssl_config, | |
| 176 const ProxyInfo& used_proxy_info, | |
| 177 HttpAuthController* auth_controller) override {} | |
| 178 | |
| 179 void OnNeedsClientAuth(const SSLConfig& used_ssl_config, | |
| 180 SSLCertRequestInfo* cert_info) override {} | |
| 181 | |
| 182 void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info, | |
| 183 const SSLConfig& used_ssl_config, | |
| 184 const ProxyInfo& used_proxy_info, | |
| 185 HttpStream* stream) override {} | |
| 186 | |
| 187 void WaitForStream() { | |
| 188 while (!stream_done_) { | |
| 189 waiting_for_stream_ = true; | |
| 190 base::MessageLoop::current()->Run(); | |
| 191 waiting_for_stream_ = false; | |
| 192 } | |
| 193 } | |
| 194 | |
| 195 const SSLConfig& used_ssl_config() const { | |
| 196 return used_ssl_config_; | |
| 197 } | |
| 198 | |
| 199 const ProxyInfo& used_proxy_info() const { | |
| 200 return used_proxy_info_; | |
| 201 } | |
| 202 | |
| 203 HttpStream* stream() { | |
| 204 return stream_.get(); | |
| 205 } | |
| 206 | |
| 207 MockWebSocketHandshakeStream* websocket_stream() { | |
| 208 return static_cast<MockWebSocketHandshakeStream*>(websocket_stream_.get()); | |
| 209 } | |
| 210 | |
| 211 bool stream_done() const { return stream_done_; } | |
| 212 | |
| 213 private: | |
| 214 bool waiting_for_stream_; | |
| 215 bool stream_done_; | |
| 216 scoped_ptr<HttpStream> stream_; | |
| 217 scoped_ptr<WebSocketHandshakeStreamBase> websocket_stream_; | |
| 218 SSLConfig used_ssl_config_; | |
| 219 ProxyInfo used_proxy_info_; | |
| 220 | |
| 221 DISALLOW_COPY_AND_ASSIGN(StreamRequestWaiter); | |
| 222 }; | |
| 223 | |
| 224 class WebSocketSpdyHandshakeStream : public MockWebSocketHandshakeStream { | |
| 225 public: | |
| 226 explicit WebSocketSpdyHandshakeStream( | |
| 227 const base::WeakPtr<SpdySession>& spdy_session) | |
| 228 : MockWebSocketHandshakeStream(kStreamTypeSpdy), | |
| 229 spdy_session_(spdy_session) {} | |
| 230 | |
| 231 ~WebSocketSpdyHandshakeStream() override {} | |
| 232 | |
| 233 SpdySession* spdy_session() { return spdy_session_.get(); } | |
| 234 | |
| 235 private: | |
| 236 base::WeakPtr<SpdySession> spdy_session_; | |
| 237 }; | |
| 238 | |
| 239 class WebSocketBasicHandshakeStream : public MockWebSocketHandshakeStream { | |
| 240 public: | |
| 241 explicit WebSocketBasicHandshakeStream( | |
| 242 scoped_ptr<ClientSocketHandle> connection) | |
| 243 : MockWebSocketHandshakeStream(kStreamTypeBasic), | |
| 244 connection_(connection.Pass()) {} | |
| 245 | |
| 246 ~WebSocketBasicHandshakeStream() override { | |
| 247 connection_->socket()->Disconnect(); | |
| 248 } | |
| 249 | |
| 250 ClientSocketHandle* connection() { return connection_.get(); } | |
| 251 | |
| 252 private: | |
| 253 scoped_ptr<ClientSocketHandle> connection_; | |
| 254 }; | |
| 255 | |
| 256 class WebSocketStreamCreateHelper | |
| 257 : public WebSocketHandshakeStreamBase::CreateHelper { | |
| 258 public: | |
| 259 ~WebSocketStreamCreateHelper() override {} | |
| 260 | |
| 261 WebSocketHandshakeStreamBase* CreateBasicStream( | |
| 262 scoped_ptr<ClientSocketHandle> connection, | |
| 263 bool using_proxy) override { | |
| 264 return new WebSocketBasicHandshakeStream(connection.Pass()); | |
| 265 } | |
| 266 | |
| 267 WebSocketHandshakeStreamBase* CreateSpdyStream( | |
| 268 const base::WeakPtr<SpdySession>& spdy_session, | |
| 269 bool use_relative_url) override { | |
| 270 return new WebSocketSpdyHandshakeStream(spdy_session); | |
| 271 } | |
| 272 }; | |
| 273 | |
| 274 struct TestCase { | |
| 275 int num_streams; | |
| 276 bool ssl; | |
| 277 }; | |
| 278 | |
| 279 TestCase kTests[] = { | |
| 280 { 1, false }, | |
| 281 { 2, false }, | |
| 282 { 1, true}, | |
| 283 { 2, true}, | |
| 284 }; | |
| 285 | |
| 286 void PreconnectHelperForURL(int num_streams, | |
| 287 const GURL& url, | |
| 288 HttpNetworkSession* session) { | |
| 289 HttpNetworkSessionPeer peer(session); | |
| 290 MockHttpStreamFactoryImplForPreconnect* mock_factory = | |
| 291 new MockHttpStreamFactoryImplForPreconnect(session, false); | |
| 292 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(mock_factory)); | |
| 293 SSLConfig ssl_config; | |
| 294 session->ssl_config_service()->GetSSLConfig(&ssl_config); | |
| 295 | |
| 296 HttpRequestInfo request; | |
| 297 request.method = "GET"; | |
| 298 request.url = url; | |
| 299 request.load_flags = 0; | |
| 300 | |
| 301 session->http_stream_factory()->PreconnectStreams( | |
| 302 num_streams, request, DEFAULT_PRIORITY, ssl_config, ssl_config); | |
| 303 mock_factory->WaitForPreconnects(); | |
| 304 }; | |
| 305 | |
| 306 void PreconnectHelper(const TestCase& test, | |
| 307 HttpNetworkSession* session) { | |
| 308 GURL url = test.ssl ? GURL("https://www.google.com") : | |
| 309 GURL("http://www.google.com"); | |
| 310 PreconnectHelperForURL(test.num_streams, url, session); | |
| 311 }; | |
| 312 | |
| 313 template<typename ParentPool> | |
| 314 class CapturePreconnectsSocketPool : public ParentPool { | |
| 315 public: | |
| 316 CapturePreconnectsSocketPool(HostResolver* host_resolver, | |
| 317 CertVerifier* cert_verifier); | |
| 318 | |
| 319 int last_num_streams() const { | |
| 320 return last_num_streams_; | |
| 321 } | |
| 322 | |
| 323 virtual int RequestSocket(const std::string& group_name, | |
| 324 const void* socket_params, | |
| 325 RequestPriority priority, | |
| 326 ClientSocketHandle* handle, | |
| 327 const CompletionCallback& callback, | |
| 328 const BoundNetLog& net_log) override { | |
| 329 ADD_FAILURE(); | |
| 330 return ERR_UNEXPECTED; | |
| 331 } | |
| 332 | |
| 333 virtual void RequestSockets(const std::string& group_name, | |
| 334 const void* socket_params, | |
| 335 int num_sockets, | |
| 336 const BoundNetLog& net_log) override { | |
| 337 last_num_streams_ = num_sockets; | |
| 338 } | |
| 339 | |
| 340 virtual void CancelRequest(const std::string& group_name, | |
| 341 ClientSocketHandle* handle) override { | |
| 342 ADD_FAILURE(); | |
| 343 } | |
| 344 virtual void ReleaseSocket(const std::string& group_name, | |
| 345 scoped_ptr<StreamSocket> socket, | |
| 346 int id) override { | |
| 347 ADD_FAILURE(); | |
| 348 } | |
| 349 virtual void CloseIdleSockets() override { | |
| 350 ADD_FAILURE(); | |
| 351 } | |
| 352 virtual int IdleSocketCount() const override { | |
| 353 ADD_FAILURE(); | |
| 354 return 0; | |
| 355 } | |
| 356 virtual int IdleSocketCountInGroup( | |
| 357 const std::string& group_name) const override { | |
| 358 ADD_FAILURE(); | |
| 359 return 0; | |
| 360 } | |
| 361 virtual LoadState GetLoadState( | |
| 362 const std::string& group_name, | |
| 363 const ClientSocketHandle* handle) const override { | |
| 364 ADD_FAILURE(); | |
| 365 return LOAD_STATE_IDLE; | |
| 366 } | |
| 367 virtual base::TimeDelta ConnectionTimeout() const override { | |
| 368 return base::TimeDelta(); | |
| 369 } | |
| 370 | |
| 371 private: | |
| 372 int last_num_streams_; | |
| 373 }; | |
| 374 | |
| 375 typedef CapturePreconnectsSocketPool<TransportClientSocketPool> | |
| 376 CapturePreconnectsTransportSocketPool; | |
| 377 typedef CapturePreconnectsSocketPool<HttpProxyClientSocketPool> | |
| 378 CapturePreconnectsHttpProxySocketPool; | |
| 379 typedef CapturePreconnectsSocketPool<SOCKSClientSocketPool> | |
| 380 CapturePreconnectsSOCKSSocketPool; | |
| 381 typedef CapturePreconnectsSocketPool<SSLClientSocketPool> | |
| 382 CapturePreconnectsSSLSocketPool; | |
| 383 | |
| 384 template<typename ParentPool> | |
| 385 CapturePreconnectsSocketPool<ParentPool>::CapturePreconnectsSocketPool( | |
| 386 HostResolver* host_resolver, CertVerifier* /* cert_verifier */) | |
| 387 : ParentPool(0, 0, nullptr, host_resolver, nullptr, nullptr), | |
| 388 last_num_streams_(-1) {} | |
| 389 | |
| 390 template <> | |
| 391 CapturePreconnectsHttpProxySocketPool::CapturePreconnectsSocketPool( | |
| 392 HostResolver* /* host_resolver */, | |
| 393 CertVerifier* /* cert_verifier */) | |
| 394 : HttpProxyClientSocketPool(0, 0, nullptr, nullptr, nullptr, nullptr), | |
| 395 last_num_streams_(-1) { | |
| 396 } | |
| 397 | |
| 398 template <> | |
| 399 CapturePreconnectsSSLSocketPool::CapturePreconnectsSocketPool( | |
| 400 HostResolver* /* host_resolver */, | |
| 401 CertVerifier* cert_verifier) | |
| 402 : SSLClientSocketPool(0, | |
| 403 0, | |
| 404 nullptr, // ssl_histograms | |
| 405 cert_verifier, | |
| 406 nullptr, // channel_id_store | |
| 407 nullptr, // transport_security_state | |
| 408 nullptr, // cert_transparency_verifier | |
| 409 nullptr, // cert_policy_enforcer | |
| 410 std::string(), // ssl_session_cache_shard | |
| 411 nullptr, // deterministic_socket_factory | |
| 412 nullptr, // transport_socket_pool | |
| 413 nullptr, | |
| 414 nullptr, | |
| 415 nullptr, // ssl_config_service | |
| 416 false, // enable_ssl_connect_job_waiting | |
| 417 nullptr), // net_log | |
| 418 last_num_streams_(-1) { | |
| 419 } | |
| 420 | |
| 421 class HttpStreamFactoryTest : public ::testing::Test, | |
| 422 public ::testing::WithParamInterface<NextProto> { | |
| 423 }; | |
| 424 | |
| 425 INSTANTIATE_TEST_CASE_P( | |
| 426 NextProto, | |
| 427 HttpStreamFactoryTest, | |
| 428 testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15)); | |
| 429 | |
| 430 TEST_P(HttpStreamFactoryTest, PreconnectDirect) { | |
| 431 for (size_t i = 0; i < arraysize(kTests); ++i) { | |
| 432 SpdySessionDependencies session_deps( | |
| 433 GetParam(), ProxyService::CreateDirect()); | |
| 434 scoped_refptr<HttpNetworkSession> session( | |
| 435 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 436 HttpNetworkSessionPeer peer(session); | |
| 437 CapturePreconnectsTransportSocketPool* transport_conn_pool = | |
| 438 new CapturePreconnectsTransportSocketPool( | |
| 439 session_deps.host_resolver.get(), | |
| 440 session_deps.cert_verifier.get()); | |
| 441 CapturePreconnectsSSLSocketPool* ssl_conn_pool = | |
| 442 new CapturePreconnectsSSLSocketPool( | |
| 443 session_deps.host_resolver.get(), | |
| 444 session_deps.cert_verifier.get()); | |
| 445 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( | |
| 446 new MockClientSocketPoolManager); | |
| 447 mock_pool_manager->SetTransportSocketPool(transport_conn_pool); | |
| 448 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool); | |
| 449 peer.SetClientSocketPoolManager(mock_pool_manager.Pass()); | |
| 450 PreconnectHelper(kTests[i], session.get()); | |
| 451 if (kTests[i].ssl) | |
| 452 EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams()); | |
| 453 else | |
| 454 EXPECT_EQ(kTests[i].num_streams, transport_conn_pool->last_num_streams()); | |
| 455 } | |
| 456 } | |
| 457 | |
| 458 TEST_P(HttpStreamFactoryTest, PreconnectHttpProxy) { | |
| 459 for (size_t i = 0; i < arraysize(kTests); ++i) { | |
| 460 SpdySessionDependencies session_deps( | |
| 461 GetParam(), ProxyService::CreateFixed("http_proxy")); | |
| 462 scoped_refptr<HttpNetworkSession> session( | |
| 463 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 464 HttpNetworkSessionPeer peer(session); | |
| 465 HostPortPair proxy_host("http_proxy", 80); | |
| 466 CapturePreconnectsHttpProxySocketPool* http_proxy_pool = | |
| 467 new CapturePreconnectsHttpProxySocketPool( | |
| 468 session_deps.host_resolver.get(), | |
| 469 session_deps.cert_verifier.get()); | |
| 470 CapturePreconnectsSSLSocketPool* ssl_conn_pool = | |
| 471 new CapturePreconnectsSSLSocketPool( | |
| 472 session_deps.host_resolver.get(), | |
| 473 session_deps.cert_verifier.get()); | |
| 474 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( | |
| 475 new MockClientSocketPoolManager); | |
| 476 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool); | |
| 477 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); | |
| 478 peer.SetClientSocketPoolManager(mock_pool_manager.Pass()); | |
| 479 PreconnectHelper(kTests[i], session.get()); | |
| 480 if (kTests[i].ssl) | |
| 481 EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams()); | |
| 482 else | |
| 483 EXPECT_EQ(kTests[i].num_streams, http_proxy_pool->last_num_streams()); | |
| 484 } | |
| 485 } | |
| 486 | |
| 487 TEST_P(HttpStreamFactoryTest, PreconnectSocksProxy) { | |
| 488 for (size_t i = 0; i < arraysize(kTests); ++i) { | |
| 489 SpdySessionDependencies session_deps( | |
| 490 GetParam(), ProxyService::CreateFixed("socks4://socks_proxy:1080")); | |
| 491 scoped_refptr<HttpNetworkSession> session( | |
| 492 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 493 HttpNetworkSessionPeer peer(session); | |
| 494 HostPortPair proxy_host("socks_proxy", 1080); | |
| 495 CapturePreconnectsSOCKSSocketPool* socks_proxy_pool = | |
| 496 new CapturePreconnectsSOCKSSocketPool( | |
| 497 session_deps.host_resolver.get(), | |
| 498 session_deps.cert_verifier.get()); | |
| 499 CapturePreconnectsSSLSocketPool* ssl_conn_pool = | |
| 500 new CapturePreconnectsSSLSocketPool( | |
| 501 session_deps.host_resolver.get(), | |
| 502 session_deps.cert_verifier.get()); | |
| 503 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( | |
| 504 new MockClientSocketPoolManager); | |
| 505 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_proxy_pool); | |
| 506 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); | |
| 507 peer.SetClientSocketPoolManager(mock_pool_manager.Pass()); | |
| 508 PreconnectHelper(kTests[i], session.get()); | |
| 509 if (kTests[i].ssl) | |
| 510 EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams()); | |
| 511 else | |
| 512 EXPECT_EQ(kTests[i].num_streams, socks_proxy_pool->last_num_streams()); | |
| 513 } | |
| 514 } | |
| 515 | |
| 516 TEST_P(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) { | |
| 517 for (size_t i = 0; i < arraysize(kTests); ++i) { | |
| 518 SpdySessionDependencies session_deps( | |
| 519 GetParam(), ProxyService::CreateDirect()); | |
| 520 scoped_refptr<HttpNetworkSession> session( | |
| 521 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 522 HttpNetworkSessionPeer peer(session); | |
| 523 | |
| 524 // Put a SpdySession in the pool. | |
| 525 HostPortPair host_port_pair("www.google.com", 443); | |
| 526 SpdySessionKey key(host_port_pair, ProxyServer::Direct(), | |
| 527 PRIVACY_MODE_DISABLED); | |
| 528 ignore_result(CreateFakeSpdySession(session->spdy_session_pool(), key)); | |
| 529 | |
| 530 CapturePreconnectsTransportSocketPool* transport_conn_pool = | |
| 531 new CapturePreconnectsTransportSocketPool( | |
| 532 session_deps.host_resolver.get(), | |
| 533 session_deps.cert_verifier.get()); | |
| 534 CapturePreconnectsSSLSocketPool* ssl_conn_pool = | |
| 535 new CapturePreconnectsSSLSocketPool( | |
| 536 session_deps.host_resolver.get(), | |
| 537 session_deps.cert_verifier.get()); | |
| 538 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( | |
| 539 new MockClientSocketPoolManager); | |
| 540 mock_pool_manager->SetTransportSocketPool(transport_conn_pool); | |
| 541 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool); | |
| 542 peer.SetClientSocketPoolManager(mock_pool_manager.Pass()); | |
| 543 PreconnectHelper(kTests[i], session.get()); | |
| 544 // We shouldn't be preconnecting if we have an existing session, which is | |
| 545 // the case for https://www.google.com. | |
| 546 if (kTests[i].ssl) | |
| 547 EXPECT_EQ(-1, ssl_conn_pool->last_num_streams()); | |
| 548 else | |
| 549 EXPECT_EQ(kTests[i].num_streams, | |
| 550 transport_conn_pool->last_num_streams()); | |
| 551 } | |
| 552 } | |
| 553 | |
| 554 // Verify that preconnects to unsafe ports are cancelled before they reach | |
| 555 // the SocketPool. | |
| 556 TEST_P(HttpStreamFactoryTest, PreconnectUnsafePort) { | |
| 557 ASSERT_FALSE(IsPortAllowedByDefault(7)); | |
| 558 ASSERT_FALSE(IsPortAllowedByOverride(7)); | |
| 559 | |
| 560 SpdySessionDependencies session_deps( | |
| 561 GetParam(), ProxyService::CreateDirect()); | |
| 562 scoped_refptr<HttpNetworkSession> session( | |
| 563 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 564 HttpNetworkSessionPeer peer(session); | |
| 565 CapturePreconnectsTransportSocketPool* transport_conn_pool = | |
| 566 new CapturePreconnectsTransportSocketPool( | |
| 567 session_deps.host_resolver.get(), | |
| 568 session_deps.cert_verifier.get()); | |
| 569 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( | |
| 570 new MockClientSocketPoolManager); | |
| 571 mock_pool_manager->SetTransportSocketPool(transport_conn_pool); | |
| 572 peer.SetClientSocketPoolManager(mock_pool_manager.Pass()); | |
| 573 | |
| 574 PreconnectHelperForURL(1, GURL("http://www.google.com:7"), session.get()); | |
| 575 | |
| 576 EXPECT_EQ(-1, transport_conn_pool->last_num_streams()); | |
| 577 } | |
| 578 | |
| 579 TEST_P(HttpStreamFactoryTest, JobNotifiesProxy) { | |
| 580 const char* kProxyString = "PROXY bad:99; PROXY maybe:80; DIRECT"; | |
| 581 SpdySessionDependencies session_deps( | |
| 582 GetParam(), ProxyService::CreateFixedFromPacResult(kProxyString)); | |
| 583 | |
| 584 // First connection attempt fails | |
| 585 StaticSocketDataProvider socket_data1; | |
| 586 socket_data1.set_connect_data(MockConnect(ASYNC, ERR_ADDRESS_UNREACHABLE)); | |
| 587 session_deps.socket_factory->AddSocketDataProvider(&socket_data1); | |
| 588 | |
| 589 // Second connection attempt succeeds | |
| 590 StaticSocketDataProvider socket_data2; | |
| 591 socket_data2.set_connect_data(MockConnect(ASYNC, OK)); | |
| 592 session_deps.socket_factory->AddSocketDataProvider(&socket_data2); | |
| 593 | |
| 594 scoped_refptr<HttpNetworkSession> session( | |
| 595 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 596 | |
| 597 // Now request a stream. It should succeed using the second proxy in the | |
| 598 // list. | |
| 599 HttpRequestInfo request_info; | |
| 600 request_info.method = "GET"; | |
| 601 request_info.url = GURL("http://www.google.com"); | |
| 602 | |
| 603 SSLConfig ssl_config; | |
| 604 StreamRequestWaiter waiter; | |
| 605 scoped_ptr<HttpStreamRequest> request( | |
| 606 session->http_stream_factory()->RequestStream( | |
| 607 request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, | |
| 608 &waiter, BoundNetLog())); | |
| 609 waiter.WaitForStream(); | |
| 610 | |
| 611 // The proxy that failed should now be known to the proxy_service as bad. | |
| 612 const ProxyRetryInfoMap& retry_info = | |
| 613 session->proxy_service()->proxy_retry_info(); | |
| 614 EXPECT_EQ(1u, retry_info.size()); | |
| 615 ProxyRetryInfoMap::const_iterator iter = retry_info.find("bad:99"); | |
| 616 EXPECT_TRUE(iter != retry_info.end()); | |
| 617 } | |
| 618 | |
| 619 TEST_P(HttpStreamFactoryTest, PrivacyModeDisablesChannelId) { | |
| 620 SpdySessionDependencies session_deps( | |
| 621 GetParam(), ProxyService::CreateDirect()); | |
| 622 | |
| 623 StaticSocketDataProvider socket_data; | |
| 624 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 625 session_deps.socket_factory->AddSocketDataProvider(&socket_data); | |
| 626 | |
| 627 SSLSocketDataProvider ssl(ASYNC, OK); | |
| 628 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl); | |
| 629 | |
| 630 scoped_refptr<HttpNetworkSession> session( | |
| 631 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 632 | |
| 633 // Set an existing SpdySession in the pool. | |
| 634 HostPortPair host_port_pair("www.google.com", 443); | |
| 635 SpdySessionKey key(host_port_pair, ProxyServer::Direct(), | |
| 636 PRIVACY_MODE_ENABLED); | |
| 637 | |
| 638 HttpRequestInfo request_info; | |
| 639 request_info.method = "GET"; | |
| 640 request_info.url = GURL("https://www.google.com"); | |
| 641 request_info.load_flags = 0; | |
| 642 request_info.privacy_mode = PRIVACY_MODE_DISABLED; | |
| 643 | |
| 644 SSLConfig ssl_config; | |
| 645 StreamRequestWaiter waiter; | |
| 646 scoped_ptr<HttpStreamRequest> request( | |
| 647 session->http_stream_factory()->RequestStream( | |
| 648 request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, | |
| 649 &waiter, BoundNetLog())); | |
| 650 waiter.WaitForStream(); | |
| 651 | |
| 652 // The stream shouldn't come from spdy as we are using different privacy mode | |
| 653 EXPECT_FALSE(request->using_spdy()); | |
| 654 | |
| 655 SSLConfig used_ssl_config = waiter.used_ssl_config(); | |
| 656 EXPECT_EQ(used_ssl_config.channel_id_enabled, ssl_config.channel_id_enabled); | |
| 657 } | |
| 658 | |
| 659 namespace { | |
| 660 // Return count of distinct groups in given socket pool. | |
| 661 int GetSocketPoolGroupCount(ClientSocketPool* pool) { | |
| 662 int count = 0; | |
| 663 scoped_ptr<base::DictionaryValue> dict(pool->GetInfoAsValue("", "", false)); | |
| 664 EXPECT_TRUE(dict != nullptr); | |
| 665 base::DictionaryValue* groups = nullptr; | |
| 666 if (dict->GetDictionary("groups", &groups) && (groups != nullptr)) { | |
| 667 count = static_cast<int>(groups->size()); | |
| 668 } | |
| 669 return count; | |
| 670 } | |
| 671 } // namespace | |
| 672 | |
| 673 TEST_P(HttpStreamFactoryTest, PrivacyModeUsesDifferentSocketPoolGroup) { | |
| 674 SpdySessionDependencies session_deps( | |
| 675 GetParam(), ProxyService::CreateDirect()); | |
| 676 | |
| 677 StaticSocketDataProvider socket_data; | |
| 678 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 679 session_deps.socket_factory->AddSocketDataProvider(&socket_data); | |
| 680 | |
| 681 SSLSocketDataProvider ssl(ASYNC, OK); | |
| 682 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl); | |
| 683 | |
| 684 scoped_refptr<HttpNetworkSession> session( | |
| 685 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 686 SSLClientSocketPool* ssl_pool = session->GetSSLSocketPool( | |
| 687 HttpNetworkSession::NORMAL_SOCKET_POOL); | |
| 688 | |
| 689 EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 0); | |
| 690 | |
| 691 HttpRequestInfo request_info; | |
| 692 request_info.method = "GET"; | |
| 693 request_info.url = GURL("https://www.google.com"); | |
| 694 request_info.load_flags = 0; | |
| 695 request_info.privacy_mode = PRIVACY_MODE_DISABLED; | |
| 696 | |
| 697 SSLConfig ssl_config; | |
| 698 StreamRequestWaiter waiter; | |
| 699 | |
| 700 scoped_ptr<HttpStreamRequest> request1( | |
| 701 session->http_stream_factory()->RequestStream( | |
| 702 request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, | |
| 703 &waiter, BoundNetLog())); | |
| 704 waiter.WaitForStream(); | |
| 705 | |
| 706 EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 1); | |
| 707 | |
| 708 scoped_ptr<HttpStreamRequest> request2( | |
| 709 session->http_stream_factory()->RequestStream( | |
| 710 request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, | |
| 711 &waiter, BoundNetLog())); | |
| 712 waiter.WaitForStream(); | |
| 713 | |
| 714 EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 1); | |
| 715 | |
| 716 request_info.privacy_mode = PRIVACY_MODE_ENABLED; | |
| 717 scoped_ptr<HttpStreamRequest> request3( | |
| 718 session->http_stream_factory()->RequestStream( | |
| 719 request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, | |
| 720 &waiter, BoundNetLog())); | |
| 721 waiter.WaitForStream(); | |
| 722 | |
| 723 EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 2); | |
| 724 } | |
| 725 | |
| 726 TEST_P(HttpStreamFactoryTest, GetLoadState) { | |
| 727 SpdySessionDependencies session_deps( | |
| 728 GetParam(), ProxyService::CreateDirect()); | |
| 729 | |
| 730 StaticSocketDataProvider socket_data; | |
| 731 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 732 session_deps.socket_factory->AddSocketDataProvider(&socket_data); | |
| 733 | |
| 734 scoped_refptr<HttpNetworkSession> session( | |
| 735 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 736 | |
| 737 HttpRequestInfo request_info; | |
| 738 request_info.method = "GET"; | |
| 739 request_info.url = GURL("http://www.google.com"); | |
| 740 | |
| 741 SSLConfig ssl_config; | |
| 742 StreamRequestWaiter waiter; | |
| 743 scoped_ptr<HttpStreamRequest> request( | |
| 744 session->http_stream_factory()->RequestStream( | |
| 745 request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, | |
| 746 &waiter, BoundNetLog())); | |
| 747 | |
| 748 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, request->GetLoadState()); | |
| 749 | |
| 750 waiter.WaitForStream(); | |
| 751 } | |
| 752 | |
| 753 TEST_P(HttpStreamFactoryTest, RequestHttpStream) { | |
| 754 SpdySessionDependencies session_deps( | |
| 755 GetParam(), ProxyService::CreateDirect()); | |
| 756 | |
| 757 StaticSocketDataProvider socket_data; | |
| 758 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 759 session_deps.socket_factory->AddSocketDataProvider(&socket_data); | |
| 760 | |
| 761 scoped_refptr<HttpNetworkSession> session( | |
| 762 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 763 | |
| 764 // Now request a stream. It should succeed using the second proxy in the | |
| 765 // list. | |
| 766 HttpRequestInfo request_info; | |
| 767 request_info.method = "GET"; | |
| 768 request_info.url = GURL("http://www.google.com"); | |
| 769 request_info.load_flags = 0; | |
| 770 | |
| 771 SSLConfig ssl_config; | |
| 772 StreamRequestWaiter waiter; | |
| 773 scoped_ptr<HttpStreamRequest> request( | |
| 774 session->http_stream_factory()->RequestStream( | |
| 775 request_info, | |
| 776 DEFAULT_PRIORITY, | |
| 777 ssl_config, | |
| 778 ssl_config, | |
| 779 &waiter, | |
| 780 BoundNetLog())); | |
| 781 waiter.WaitForStream(); | |
| 782 EXPECT_TRUE(waiter.stream_done()); | |
| 783 ASSERT_TRUE(nullptr != waiter.stream()); | |
| 784 EXPECT_TRUE(nullptr == waiter.websocket_stream()); | |
| 785 EXPECT_FALSE(waiter.stream()->IsSpdyHttpStream()); | |
| 786 | |
| 787 EXPECT_EQ(1, GetSocketPoolGroupCount( | |
| 788 session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 789 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSSLSocketPool( | |
| 790 HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 791 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 792 session->GetTransportSocketPool( | |
| 793 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 794 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSSLSocketPool( | |
| 795 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 796 EXPECT_TRUE(waiter.used_proxy_info().is_direct()); | |
| 797 } | |
| 798 | |
| 799 TEST_P(HttpStreamFactoryTest, RequestHttpStreamOverSSL) { | |
| 800 SpdySessionDependencies session_deps( | |
| 801 GetParam(), ProxyService::CreateDirect()); | |
| 802 | |
| 803 MockRead mock_read(ASYNC, OK); | |
| 804 StaticSocketDataProvider socket_data(&mock_read, 1, nullptr, 0); | |
| 805 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 806 session_deps.socket_factory->AddSocketDataProvider(&socket_data); | |
| 807 | |
| 808 SSLSocketDataProvider ssl_socket_data(ASYNC, OK); | |
| 809 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data); | |
| 810 | |
| 811 scoped_refptr<HttpNetworkSession> session( | |
| 812 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 813 | |
| 814 // Now request a stream. | |
| 815 HttpRequestInfo request_info; | |
| 816 request_info.method = "GET"; | |
| 817 request_info.url = GURL("https://www.google.com"); | |
| 818 request_info.load_flags = 0; | |
| 819 | |
| 820 SSLConfig ssl_config; | |
| 821 StreamRequestWaiter waiter; | |
| 822 scoped_ptr<HttpStreamRequest> request( | |
| 823 session->http_stream_factory()->RequestStream( | |
| 824 request_info, | |
| 825 DEFAULT_PRIORITY, | |
| 826 ssl_config, | |
| 827 ssl_config, | |
| 828 &waiter, | |
| 829 BoundNetLog())); | |
| 830 waiter.WaitForStream(); | |
| 831 EXPECT_TRUE(waiter.stream_done()); | |
| 832 ASSERT_TRUE(nullptr != waiter.stream()); | |
| 833 EXPECT_TRUE(nullptr == waiter.websocket_stream()); | |
| 834 EXPECT_FALSE(waiter.stream()->IsSpdyHttpStream()); | |
| 835 EXPECT_EQ(1, GetSocketPoolGroupCount( | |
| 836 session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 837 EXPECT_EQ(1, GetSocketPoolGroupCount( | |
| 838 session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 839 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 840 session->GetTransportSocketPool( | |
| 841 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 842 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSSLSocketPool( | |
| 843 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 844 EXPECT_TRUE(waiter.used_proxy_info().is_direct()); | |
| 845 } | |
| 846 | |
| 847 TEST_P(HttpStreamFactoryTest, RequestHttpStreamOverProxy) { | |
| 848 SpdySessionDependencies session_deps( | |
| 849 GetParam(), ProxyService::CreateFixed("myproxy:8888")); | |
| 850 | |
| 851 StaticSocketDataProvider socket_data; | |
| 852 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 853 session_deps.socket_factory->AddSocketDataProvider(&socket_data); | |
| 854 | |
| 855 scoped_refptr<HttpNetworkSession> session( | |
| 856 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 857 | |
| 858 // Now request a stream. It should succeed using the second proxy in the | |
| 859 // list. | |
| 860 HttpRequestInfo request_info; | |
| 861 request_info.method = "GET"; | |
| 862 request_info.url = GURL("http://www.google.com"); | |
| 863 request_info.load_flags = 0; | |
| 864 | |
| 865 SSLConfig ssl_config; | |
| 866 StreamRequestWaiter waiter; | |
| 867 scoped_ptr<HttpStreamRequest> request( | |
| 868 session->http_stream_factory()->RequestStream( | |
| 869 request_info, | |
| 870 DEFAULT_PRIORITY, | |
| 871 ssl_config, | |
| 872 ssl_config, | |
| 873 &waiter, | |
| 874 BoundNetLog())); | |
| 875 waiter.WaitForStream(); | |
| 876 EXPECT_TRUE(waiter.stream_done()); | |
| 877 ASSERT_TRUE(nullptr != waiter.stream()); | |
| 878 EXPECT_TRUE(nullptr == waiter.websocket_stream()); | |
| 879 EXPECT_FALSE(waiter.stream()->IsSpdyHttpStream()); | |
| 880 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 881 session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 882 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 883 session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 884 EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSocketPoolForHTTPProxy( | |
| 885 HttpNetworkSession::NORMAL_SOCKET_POOL, | |
| 886 HostPortPair("myproxy", 8888)))); | |
| 887 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPoolForSSLWithProxy( | |
| 888 HttpNetworkSession::NORMAL_SOCKET_POOL, | |
| 889 HostPortPair("myproxy", 8888)))); | |
| 890 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPoolForHTTPProxy( | |
| 891 HttpNetworkSession::WEBSOCKET_SOCKET_POOL, | |
| 892 HostPortPair("myproxy", 8888)))); | |
| 893 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPoolForSSLWithProxy( | |
| 894 HttpNetworkSession::WEBSOCKET_SOCKET_POOL, | |
| 895 HostPortPair("myproxy", 8888)))); | |
| 896 EXPECT_FALSE(waiter.used_proxy_info().is_direct()); | |
| 897 } | |
| 898 | |
| 899 TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStream) { | |
| 900 SpdySessionDependencies session_deps( | |
| 901 GetParam(), ProxyService::CreateDirect()); | |
| 902 | |
| 903 StaticSocketDataProvider socket_data; | |
| 904 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 905 session_deps.socket_factory->AddSocketDataProvider(&socket_data); | |
| 906 | |
| 907 scoped_refptr<HttpNetworkSession> session( | |
| 908 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 909 | |
| 910 // Now request a stream. | |
| 911 HttpRequestInfo request_info; | |
| 912 request_info.method = "GET"; | |
| 913 request_info.url = GURL("ws://www.google.com"); | |
| 914 request_info.load_flags = 0; | |
| 915 | |
| 916 SSLConfig ssl_config; | |
| 917 StreamRequestWaiter waiter; | |
| 918 WebSocketStreamCreateHelper create_helper; | |
| 919 scoped_ptr<HttpStreamRequest> request( | |
| 920 session->http_stream_factory_for_websocket() | |
| 921 ->RequestWebSocketHandshakeStream(request_info, | |
| 922 DEFAULT_PRIORITY, | |
| 923 ssl_config, | |
| 924 ssl_config, | |
| 925 &waiter, | |
| 926 &create_helper, | |
| 927 BoundNetLog())); | |
| 928 waiter.WaitForStream(); | |
| 929 EXPECT_TRUE(waiter.stream_done()); | |
| 930 EXPECT_TRUE(nullptr == waiter.stream()); | |
| 931 ASSERT_TRUE(nullptr != waiter.websocket_stream()); | |
| 932 EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic, | |
| 933 waiter.websocket_stream()->type()); | |
| 934 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 935 session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 936 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 937 session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 938 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 939 session->GetSSLSocketPool(HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 940 EXPECT_TRUE(waiter.used_proxy_info().is_direct()); | |
| 941 } | |
| 942 | |
| 943 TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverSSL) { | |
| 944 SpdySessionDependencies session_deps( | |
| 945 GetParam(), ProxyService::CreateDirect()); | |
| 946 | |
| 947 MockRead mock_read(ASYNC, OK); | |
| 948 StaticSocketDataProvider socket_data(&mock_read, 1, nullptr, 0); | |
| 949 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 950 session_deps.socket_factory->AddSocketDataProvider(&socket_data); | |
| 951 | |
| 952 SSLSocketDataProvider ssl_socket_data(ASYNC, OK); | |
| 953 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data); | |
| 954 | |
| 955 scoped_refptr<HttpNetworkSession> session( | |
| 956 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 957 | |
| 958 // Now request a stream. | |
| 959 HttpRequestInfo request_info; | |
| 960 request_info.method = "GET"; | |
| 961 request_info.url = GURL("wss://www.google.com"); | |
| 962 request_info.load_flags = 0; | |
| 963 | |
| 964 SSLConfig ssl_config; | |
| 965 StreamRequestWaiter waiter; | |
| 966 WebSocketStreamCreateHelper create_helper; | |
| 967 scoped_ptr<HttpStreamRequest> request( | |
| 968 session->http_stream_factory_for_websocket() | |
| 969 ->RequestWebSocketHandshakeStream(request_info, | |
| 970 DEFAULT_PRIORITY, | |
| 971 ssl_config, | |
| 972 ssl_config, | |
| 973 &waiter, | |
| 974 &create_helper, | |
| 975 BoundNetLog())); | |
| 976 waiter.WaitForStream(); | |
| 977 EXPECT_TRUE(waiter.stream_done()); | |
| 978 EXPECT_TRUE(nullptr == waiter.stream()); | |
| 979 ASSERT_TRUE(nullptr != waiter.websocket_stream()); | |
| 980 EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic, | |
| 981 waiter.websocket_stream()->type()); | |
| 982 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 983 session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 984 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 985 session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 986 EXPECT_EQ(1, GetSocketPoolGroupCount( | |
| 987 session->GetSSLSocketPool(HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 988 EXPECT_TRUE(waiter.used_proxy_info().is_direct()); | |
| 989 } | |
| 990 | |
| 991 TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverProxy) { | |
| 992 SpdySessionDependencies session_deps( | |
| 993 GetParam(), ProxyService::CreateFixed("myproxy:8888")); | |
| 994 | |
| 995 MockRead read(SYNCHRONOUS, "HTTP/1.0 200 Connection established\r\n\r\n"); | |
| 996 StaticSocketDataProvider socket_data(&read, 1, 0, 0); | |
| 997 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 998 session_deps.socket_factory->AddSocketDataProvider(&socket_data); | |
| 999 | |
| 1000 scoped_refptr<HttpNetworkSession> session( | |
| 1001 SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 1002 | |
| 1003 // Now request a stream. | |
| 1004 HttpRequestInfo request_info; | |
| 1005 request_info.method = "GET"; | |
| 1006 request_info.url = GURL("ws://www.google.com"); | |
| 1007 request_info.load_flags = 0; | |
| 1008 | |
| 1009 SSLConfig ssl_config; | |
| 1010 StreamRequestWaiter waiter; | |
| 1011 WebSocketStreamCreateHelper create_helper; | |
| 1012 scoped_ptr<HttpStreamRequest> request( | |
| 1013 session->http_stream_factory_for_websocket() | |
| 1014 ->RequestWebSocketHandshakeStream(request_info, | |
| 1015 DEFAULT_PRIORITY, | |
| 1016 ssl_config, | |
| 1017 ssl_config, | |
| 1018 &waiter, | |
| 1019 &create_helper, | |
| 1020 BoundNetLog())); | |
| 1021 waiter.WaitForStream(); | |
| 1022 EXPECT_TRUE(waiter.stream_done()); | |
| 1023 EXPECT_TRUE(nullptr == waiter.stream()); | |
| 1024 ASSERT_TRUE(nullptr != waiter.websocket_stream()); | |
| 1025 EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic, | |
| 1026 waiter.websocket_stream()->type()); | |
| 1027 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 1028 session->GetTransportSocketPool( | |
| 1029 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 1030 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 1031 session->GetSSLSocketPool(HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 1032 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPoolForHTTPProxy( | |
| 1033 HttpNetworkSession::NORMAL_SOCKET_POOL, | |
| 1034 HostPortPair("myproxy", 8888)))); | |
| 1035 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPoolForSSLWithProxy( | |
| 1036 HttpNetworkSession::NORMAL_SOCKET_POOL, | |
| 1037 HostPortPair("myproxy", 8888)))); | |
| 1038 EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSocketPoolForHTTPProxy( | |
| 1039 HttpNetworkSession::WEBSOCKET_SOCKET_POOL, | |
| 1040 HostPortPair("myproxy", 8888)))); | |
| 1041 EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSocketPoolForSSLWithProxy( | |
| 1042 HttpNetworkSession::WEBSOCKET_SOCKET_POOL, | |
| 1043 HostPortPair("myproxy", 8888)))); | |
| 1044 EXPECT_FALSE(waiter.used_proxy_info().is_direct()); | |
| 1045 } | |
| 1046 | |
| 1047 TEST_P(HttpStreamFactoryTest, RequestSpdyHttpStream) { | |
| 1048 SpdySessionDependencies session_deps(GetParam(), | |
| 1049 ProxyService::CreateDirect()); | |
| 1050 | |
| 1051 MockRead mock_read(ASYNC, OK); | |
| 1052 DeterministicSocketData socket_data(&mock_read, 1, nullptr, 0); | |
| 1053 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 1054 session_deps.deterministic_socket_factory->AddSocketDataProvider( | |
| 1055 &socket_data); | |
| 1056 | |
| 1057 SSLSocketDataProvider ssl_socket_data(ASYNC, OK); | |
| 1058 ssl_socket_data.SetNextProto(GetParam()); | |
| 1059 session_deps.deterministic_socket_factory->AddSSLSocketDataProvider( | |
| 1060 &ssl_socket_data); | |
| 1061 | |
| 1062 HostPortPair host_port_pair("www.google.com", 443); | |
| 1063 scoped_refptr<HttpNetworkSession> | |
| 1064 session(SpdySessionDependencies::SpdyCreateSessionDeterministic( | |
| 1065 &session_deps)); | |
| 1066 | |
| 1067 // Now request a stream. | |
| 1068 HttpRequestInfo request_info; | |
| 1069 request_info.method = "GET"; | |
| 1070 request_info.url = GURL("https://www.google.com"); | |
| 1071 request_info.load_flags = 0; | |
| 1072 | |
| 1073 SSLConfig ssl_config; | |
| 1074 StreamRequestWaiter waiter; | |
| 1075 scoped_ptr<HttpStreamRequest> request( | |
| 1076 session->http_stream_factory()->RequestStream( | |
| 1077 request_info, | |
| 1078 DEFAULT_PRIORITY, | |
| 1079 ssl_config, | |
| 1080 ssl_config, | |
| 1081 &waiter, | |
| 1082 BoundNetLog())); | |
| 1083 waiter.WaitForStream(); | |
| 1084 EXPECT_TRUE(waiter.stream_done()); | |
| 1085 EXPECT_TRUE(nullptr == waiter.websocket_stream()); | |
| 1086 ASSERT_TRUE(nullptr != waiter.stream()); | |
| 1087 EXPECT_TRUE(waiter.stream()->IsSpdyHttpStream()); | |
| 1088 EXPECT_EQ(1, GetSocketPoolGroupCount( | |
| 1089 session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 1090 EXPECT_EQ(1, GetSocketPoolGroupCount( | |
| 1091 session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 1092 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 1093 session->GetTransportSocketPool( | |
| 1094 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 1095 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 1096 session->GetSSLSocketPool(HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 1097 EXPECT_TRUE(waiter.used_proxy_info().is_direct()); | |
| 1098 } | |
| 1099 | |
| 1100 // TODO(ricea): This test can be removed once the new WebSocket stack supports | |
| 1101 // SPDY. Currently, even if we connect to a SPDY-supporting server, we need to | |
| 1102 // use plain SSL. | |
| 1103 TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyHandshakeStreamButGetSSL) { | |
| 1104 SpdySessionDependencies session_deps(GetParam(), | |
| 1105 ProxyService::CreateDirect()); | |
| 1106 | |
| 1107 MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING); | |
| 1108 StaticSocketDataProvider socket_data(&mock_read, 1, nullptr, 0); | |
| 1109 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 1110 session_deps.socket_factory->AddSocketDataProvider(&socket_data); | |
| 1111 | |
| 1112 SSLSocketDataProvider ssl_socket_data(ASYNC, OK); | |
| 1113 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data); | |
| 1114 | |
| 1115 HostPortPair host_port_pair("www.google.com", 80); | |
| 1116 scoped_refptr<HttpNetworkSession> | |
| 1117 session(SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 1118 | |
| 1119 // Now request a stream. | |
| 1120 HttpRequestInfo request_info; | |
| 1121 request_info.method = "GET"; | |
| 1122 request_info.url = GURL("wss://www.google.com"); | |
| 1123 request_info.load_flags = 0; | |
| 1124 | |
| 1125 SSLConfig ssl_config; | |
| 1126 StreamRequestWaiter waiter1; | |
| 1127 WebSocketStreamCreateHelper create_helper; | |
| 1128 scoped_ptr<HttpStreamRequest> request1( | |
| 1129 session->http_stream_factory_for_websocket() | |
| 1130 ->RequestWebSocketHandshakeStream(request_info, | |
| 1131 DEFAULT_PRIORITY, | |
| 1132 ssl_config, | |
| 1133 ssl_config, | |
| 1134 &waiter1, | |
| 1135 &create_helper, | |
| 1136 BoundNetLog())); | |
| 1137 waiter1.WaitForStream(); | |
| 1138 EXPECT_TRUE(waiter1.stream_done()); | |
| 1139 ASSERT_TRUE(nullptr != waiter1.websocket_stream()); | |
| 1140 EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic, | |
| 1141 waiter1.websocket_stream()->type()); | |
| 1142 EXPECT_TRUE(nullptr == waiter1.stream()); | |
| 1143 | |
| 1144 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 1145 session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 1146 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 1147 session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 1148 EXPECT_EQ(1, GetSocketPoolGroupCount( | |
| 1149 session->GetSSLSocketPool(HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 1150 EXPECT_TRUE(waiter1.used_proxy_info().is_direct()); | |
| 1151 } | |
| 1152 | |
| 1153 // TODO(ricea): Re-enable once WebSocket-over-SPDY is implemented. | |
| 1154 TEST_P(HttpStreamFactoryTest, DISABLED_RequestWebSocketSpdyHandshakeStream) { | |
| 1155 SpdySessionDependencies session_deps(GetParam(), | |
| 1156 ProxyService::CreateDirect()); | |
| 1157 | |
| 1158 MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING); | |
| 1159 StaticSocketDataProvider socket_data(&mock_read, 1, nullptr, 0); | |
| 1160 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 1161 session_deps.socket_factory->AddSocketDataProvider(&socket_data); | |
| 1162 | |
| 1163 SSLSocketDataProvider ssl_socket_data(ASYNC, OK); | |
| 1164 ssl_socket_data.SetNextProto(GetParam()); | |
| 1165 session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data); | |
| 1166 | |
| 1167 HostPortPair host_port_pair("www.google.com", 80); | |
| 1168 scoped_refptr<HttpNetworkSession> | |
| 1169 session(SpdySessionDependencies::SpdyCreateSession(&session_deps)); | |
| 1170 | |
| 1171 // Now request a stream. | |
| 1172 HttpRequestInfo request_info; | |
| 1173 request_info.method = "GET"; | |
| 1174 request_info.url = GURL("wss://www.google.com"); | |
| 1175 request_info.load_flags = 0; | |
| 1176 | |
| 1177 SSLConfig ssl_config; | |
| 1178 StreamRequestWaiter waiter1; | |
| 1179 WebSocketStreamCreateHelper create_helper; | |
| 1180 scoped_ptr<HttpStreamRequest> request1( | |
| 1181 session->http_stream_factory_for_websocket() | |
| 1182 ->RequestWebSocketHandshakeStream(request_info, | |
| 1183 DEFAULT_PRIORITY, | |
| 1184 ssl_config, | |
| 1185 ssl_config, | |
| 1186 &waiter1, | |
| 1187 &create_helper, | |
| 1188 BoundNetLog())); | |
| 1189 waiter1.WaitForStream(); | |
| 1190 EXPECT_TRUE(waiter1.stream_done()); | |
| 1191 ASSERT_TRUE(nullptr != waiter1.websocket_stream()); | |
| 1192 EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeSpdy, | |
| 1193 waiter1.websocket_stream()->type()); | |
| 1194 EXPECT_TRUE(nullptr == waiter1.stream()); | |
| 1195 | |
| 1196 StreamRequestWaiter waiter2; | |
| 1197 scoped_ptr<HttpStreamRequest> request2( | |
| 1198 session->http_stream_factory_for_websocket() | |
| 1199 ->RequestWebSocketHandshakeStream(request_info, | |
| 1200 DEFAULT_PRIORITY, | |
| 1201 ssl_config, | |
| 1202 ssl_config, | |
| 1203 &waiter2, | |
| 1204 &create_helper, | |
| 1205 BoundNetLog())); | |
| 1206 waiter2.WaitForStream(); | |
| 1207 EXPECT_TRUE(waiter2.stream_done()); | |
| 1208 ASSERT_TRUE(nullptr != waiter2.websocket_stream()); | |
| 1209 EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeSpdy, | |
| 1210 waiter2.websocket_stream()->type()); | |
| 1211 EXPECT_TRUE(nullptr == waiter2.stream()); | |
| 1212 EXPECT_NE(waiter2.websocket_stream(), waiter1.websocket_stream()); | |
| 1213 EXPECT_EQ(static_cast<WebSocketSpdyHandshakeStream*>( | |
| 1214 waiter2.websocket_stream())->spdy_session(), | |
| 1215 static_cast<WebSocketSpdyHandshakeStream*>( | |
| 1216 waiter1.websocket_stream())->spdy_session()); | |
| 1217 | |
| 1218 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 1219 session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 1220 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 1221 session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 1222 EXPECT_EQ(1, GetSocketPoolGroupCount( | |
| 1223 session->GetTransportSocketPool( | |
| 1224 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 1225 EXPECT_EQ(1, GetSocketPoolGroupCount( | |
| 1226 session->GetSSLSocketPool(HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 1227 EXPECT_TRUE(waiter1.used_proxy_info().is_direct()); | |
| 1228 } | |
| 1229 | |
| 1230 // TODO(ricea): Re-enable once WebSocket over SPDY is implemented. | |
| 1231 TEST_P(HttpStreamFactoryTest, DISABLED_OrphanedWebSocketStream) { | |
| 1232 SpdySessionDependencies session_deps(GetParam(), | |
| 1233 ProxyService::CreateDirect()); | |
| 1234 session_deps.use_alternate_protocols = true; | |
| 1235 | |
| 1236 MockRead mock_read(ASYNC, OK); | |
| 1237 DeterministicSocketData socket_data(&mock_read, 1, nullptr, 0); | |
| 1238 socket_data.set_connect_data(MockConnect(ASYNC, OK)); | |
| 1239 session_deps.deterministic_socket_factory->AddSocketDataProvider( | |
| 1240 &socket_data); | |
| 1241 | |
| 1242 MockRead mock_read2(ASYNC, OK); | |
| 1243 DeterministicSocketData socket_data2(&mock_read2, 1, nullptr, 0); | |
| 1244 socket_data2.set_connect_data(MockConnect(ASYNC, ERR_IO_PENDING)); | |
| 1245 session_deps.deterministic_socket_factory->AddSocketDataProvider( | |
| 1246 &socket_data2); | |
| 1247 | |
| 1248 SSLSocketDataProvider ssl_socket_data(ASYNC, OK); | |
| 1249 ssl_socket_data.SetNextProto(GetParam()); | |
| 1250 session_deps.deterministic_socket_factory->AddSSLSocketDataProvider( | |
| 1251 &ssl_socket_data); | |
| 1252 | |
| 1253 scoped_refptr<HttpNetworkSession> | |
| 1254 session(SpdySessionDependencies::SpdyCreateSessionDeterministic( | |
| 1255 &session_deps)); | |
| 1256 | |
| 1257 // Now request a stream. | |
| 1258 HttpRequestInfo request_info; | |
| 1259 request_info.method = "GET"; | |
| 1260 request_info.url = GURL("ws://www.google.com:8888"); | |
| 1261 request_info.load_flags = 0; | |
| 1262 | |
| 1263 session->http_server_properties()->SetAlternateProtocol( | |
| 1264 HostPortPair("www.google.com", 8888), 9999, NPN_SPDY_3, 1.0); | |
| 1265 | |
| 1266 SSLConfig ssl_config; | |
| 1267 StreamRequestWaiter waiter; | |
| 1268 WebSocketStreamCreateHelper create_helper; | |
| 1269 scoped_ptr<HttpStreamRequest> request( | |
| 1270 session->http_stream_factory_for_websocket() | |
| 1271 ->RequestWebSocketHandshakeStream(request_info, | |
| 1272 DEFAULT_PRIORITY, | |
| 1273 ssl_config, | |
| 1274 ssl_config, | |
| 1275 &waiter, | |
| 1276 &create_helper, | |
| 1277 BoundNetLog())); | |
| 1278 waiter.WaitForStream(); | |
| 1279 EXPECT_TRUE(waiter.stream_done()); | |
| 1280 EXPECT_TRUE(nullptr == waiter.stream()); | |
| 1281 ASSERT_TRUE(nullptr != waiter.websocket_stream()); | |
| 1282 EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeSpdy, | |
| 1283 waiter.websocket_stream()->type()); | |
| 1284 | |
| 1285 // Make sure that there was an alternative connection | |
| 1286 // which consumes extra connections. | |
| 1287 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 1288 session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 1289 EXPECT_EQ(0, GetSocketPoolGroupCount( | |
| 1290 session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); | |
| 1291 EXPECT_EQ(2, GetSocketPoolGroupCount( | |
| 1292 session->GetTransportSocketPool( | |
| 1293 HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 1294 EXPECT_EQ(1, GetSocketPoolGroupCount( | |
| 1295 session->GetSSLSocketPool(HttpNetworkSession::WEBSOCKET_SOCKET_POOL))); | |
| 1296 EXPECT_TRUE(waiter.used_proxy_info().is_direct()); | |
| 1297 | |
| 1298 // Make sure there is no orphaned job. it is already canceled. | |
| 1299 ASSERT_EQ(0u, static_cast<HttpStreamFactoryImpl*>( | |
| 1300 session->http_stream_factory_for_websocket())->num_orphaned_jobs()); | |
| 1301 } | |
| 1302 | |
| 1303 } // namespace | |
| 1304 | |
| 1305 } // namespace net | |
| OLD | NEW |