1 // Copyright (c) 2011 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
9 #include "base/basictypes.h"
10 #include "net/base/cert_verifier.h"
11 #include "net/base/mock_host_resolver.h"
12 #include "net/base/net_log.h"
13 #include "net/base/ssl_config_service_defaults.h"
14 #include "net/base/test_completion_callback.h"
15 #include "net/http/http_auth_handler_factory.h"
16 #include "net/http/http_network_session.h"
17 #include "net/http/http_network_session_peer.h"
18 #include "net/http/http_request_info.h"
19 #include "net/proxy/proxy_info.h"
20 #include "net/proxy/proxy_service.h"
21 #include "net/socket/socket_test_util.h"
22 #include "net/spdy/spdy_session.h"
23 #include "net/spdy/spdy_session_pool.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace net {
27
28 namespace {
29
30 class MockHttpStreamFactoryImpl : public HttpStreamFactoryImpl {
31 public:
MockHttpStreamFactoryImpl(HttpNetworkSession * session)32 MockHttpStreamFactoryImpl(HttpNetworkSession* session)
33 : HttpStreamFactoryImpl(session),
34 preconnect_done_(false),
35 waiting_for_preconnect_(false) {}
36
37
WaitForPreconnects()38 void WaitForPreconnects() {
39 while (!preconnect_done_) {
40 waiting_for_preconnect_ = true;
41 MessageLoop::current()->Run();
42 waiting_for_preconnect_ = false;
43 }
44 }
45
46 private:
47 // HttpStreamFactoryImpl methods.
OnPreconnectsCompleteInternal()48 virtual void OnPreconnectsCompleteInternal() {
49 preconnect_done_ = true;
50 if (waiting_for_preconnect_)
51 MessageLoop::current()->Quit();
52 }
53
54 bool preconnect_done_;
55 bool waiting_for_preconnect_;
56 };
57
58 struct SessionDependencies {
59 // Custom proxy service dependency.
SessionDependenciesnet::__anond150a3b90111::SessionDependencies60 explicit SessionDependencies(ProxyService* proxy_service)
61 : host_resolver(new MockHostResolver),
62 cert_verifier(new CertVerifier),
63 proxy_service(proxy_service),
64 ssl_config_service(new SSLConfigServiceDefaults),
65 http_auth_handler_factory(
66 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
67 net_log(NULL) {}
68
69 scoped_ptr<MockHostResolverBase> host_resolver;
70 scoped_ptr<CertVerifier> cert_verifier;
71 scoped_refptr<ProxyService> proxy_service;
72 scoped_refptr<SSLConfigService> ssl_config_service;
73 MockClientSocketFactory socket_factory;
74 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
75 NetLog* net_log;
76 };
77
CreateSession(SessionDependencies * session_deps)78 HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
79 HttpNetworkSession::Params params;
80 params.host_resolver = session_deps->host_resolver.get();
81 params.cert_verifier = session_deps->cert_verifier.get();
82 params.proxy_service = session_deps->proxy_service;
83 params.ssl_config_service = session_deps->ssl_config_service;
84 params.client_socket_factory = &session_deps->socket_factory;
85 params.http_auth_handler_factory =
86 session_deps->http_auth_handler_factory.get();
87 params.net_log = session_deps->net_log;
88 return new HttpNetworkSession(params);
89 }
90
91 struct TestCase {
92 int num_streams;
93 bool ssl;
94 };
95
96 TestCase kTests[] = {
97 { 1, false },
98 { 2, false },
99 { 1, true},
100 { 2, true},
101 };
102
PreconnectHelper(const TestCase & test,HttpNetworkSession * session)103 void PreconnectHelper(const TestCase& test,
104 HttpNetworkSession* session) {
105 HttpNetworkSessionPeer peer(session);
106 MockHttpStreamFactoryImpl* mock_factory =
107 new MockHttpStreamFactoryImpl(session);
108 peer.SetHttpStreamFactory(mock_factory);
109 SSLConfig ssl_config;
110 session->ssl_config_service()->GetSSLConfig(&ssl_config);
111
112 HttpRequestInfo request;
113 request.method = "GET";
114 request.url = test.ssl ? GURL("https://www.google.com") :
115 GURL("http://www.google.com");
116 request.load_flags = 0;
117
118 ProxyInfo proxy_info;
119 TestCompletionCallback callback;
120
121 session->http_stream_factory()->PreconnectStreams(
122 test.num_streams, request, ssl_config, BoundNetLog());
123 mock_factory->WaitForPreconnects();
124 };
125
126 template<typename ParentPool>
127 class CapturePreconnectsSocketPool : public ParentPool {
128 public:
129 CapturePreconnectsSocketPool(HostResolver* host_resolver,
130 CertVerifier* cert_verifier);
131
last_num_streams() const132 int last_num_streams() const {
133 return last_num_streams_;
134 }
135
RequestSocket(const std::string & group_name,const void * socket_params,RequestPriority priority,ClientSocketHandle * handle,CompletionCallback * callback,const BoundNetLog & net_log)136 virtual int RequestSocket(const std::string& group_name,
137 const void* socket_params,
138 RequestPriority priority,
139 ClientSocketHandle* handle,
140 CompletionCallback* callback,
141 const BoundNetLog& net_log) {
142 ADD_FAILURE();
143 return ERR_UNEXPECTED;
144 }
145
RequestSockets(const std::string & group_name,const void * socket_params,int num_sockets,const BoundNetLog & net_log)146 virtual void RequestSockets(const std::string& group_name,
147 const void* socket_params,
148 int num_sockets,
149 const BoundNetLog& net_log) {
150 last_num_streams_ = num_sockets;
151 }
152
CancelRequest(const std::string & group_name,ClientSocketHandle * handle)153 virtual void CancelRequest(const std::string& group_name,
154 ClientSocketHandle* handle) {
155 ADD_FAILURE();
156 }
ReleaseSocket(const std::string & group_name,ClientSocket * socket,int id)157 virtual void ReleaseSocket(const std::string& group_name,
158 ClientSocket* socket,
159 int id) {
160 ADD_FAILURE();
161 }
CloseIdleSockets()162 virtual void CloseIdleSockets() {
163 ADD_FAILURE();
164 }
IdleSocketCount() const165 virtual int IdleSocketCount() const {
166 ADD_FAILURE();
167 return 0;
168 }
IdleSocketCountInGroup(const std::string & group_name) const169 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
170 ADD_FAILURE();
171 return 0;
172 }
GetLoadState(const std::string & group_name,const ClientSocketHandle * handle) const173 virtual LoadState GetLoadState(const std::string& group_name,
174 const ClientSocketHandle* handle) const {
175 ADD_FAILURE();
176 return LOAD_STATE_IDLE;
177 }
ConnectionTimeout() const178 virtual base::TimeDelta ConnectionTimeout() const {
179 return base::TimeDelta();
180 }
181
182 private:
183 int last_num_streams_;
184 };
185
186 typedef CapturePreconnectsSocketPool<TransportClientSocketPool>
187 CapturePreconnectsTransportSocketPool;
188 typedef CapturePreconnectsSocketPool<HttpProxyClientSocketPool>
189 CapturePreconnectsHttpProxySocketPool;
190 typedef CapturePreconnectsSocketPool<SOCKSClientSocketPool>
191 CapturePreconnectsSOCKSSocketPool;
192 typedef CapturePreconnectsSocketPool<SSLClientSocketPool>
193 CapturePreconnectsSSLSocketPool;
194
195 template<typename ParentPool>
CapturePreconnectsSocketPool(HostResolver * host_resolver,CertVerifier *)196 CapturePreconnectsSocketPool<ParentPool>::CapturePreconnectsSocketPool(
197 HostResolver* host_resolver, CertVerifier* /* cert_verifier */)
198 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL),
199 last_num_streams_(-1) {}
200
201 template<>
CapturePreconnectsSocketPool(HostResolver * host_resolver,CertVerifier *)202 CapturePreconnectsHttpProxySocketPool::CapturePreconnectsSocketPool(
203 HostResolver* host_resolver, CertVerifier* /* cert_verifier */)
204 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL),
205 last_num_streams_(-1) {}
206
207 template<>
CapturePreconnectsSocketPool(HostResolver * host_resolver,CertVerifier * cert_verifier)208 CapturePreconnectsSSLSocketPool::CapturePreconnectsSocketPool(
209 HostResolver* host_resolver, CertVerifier* cert_verifier)
210 : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL, NULL,
211 NULL, NULL, NULL, NULL, NULL, NULL, NULL),
212 last_num_streams_(-1) {}
213
TEST(HttpStreamFactoryTest,PreconnectDirect)214 TEST(HttpStreamFactoryTest, PreconnectDirect) {
215 for (size_t i = 0; i < arraysize(kTests); ++i) {
216 SessionDependencies session_deps(ProxyService::CreateDirect());
217 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
218 HttpNetworkSessionPeer peer(session);
219 CapturePreconnectsTransportSocketPool* transport_conn_pool =
220 new CapturePreconnectsTransportSocketPool(
221 session_deps.host_resolver.get(),
222 session_deps.cert_verifier.get());
223 peer.SetTransportSocketPool(transport_conn_pool);
224 CapturePreconnectsSSLSocketPool* ssl_conn_pool =
225 new CapturePreconnectsSSLSocketPool(
226 session_deps.host_resolver.get(),
227 session_deps.cert_verifier.get());
228 peer.SetSSLSocketPool(ssl_conn_pool);
229 PreconnectHelper(kTests[i], session);
230 if (kTests[i].ssl)
231 EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams());
232 else
233 EXPECT_EQ(kTests[i].num_streams, transport_conn_pool->last_num_streams());
234 }
235 }
236
TEST(HttpStreamFactoryTest,PreconnectHttpProxy)237 TEST(HttpStreamFactoryTest, PreconnectHttpProxy) {
238 for (size_t i = 0; i < arraysize(kTests); ++i) {
239 SessionDependencies session_deps(ProxyService::CreateFixed("http_proxy"));
240 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
241 HttpNetworkSessionPeer peer(session);
242 HostPortPair proxy_host("http_proxy", 80);
243 CapturePreconnectsHttpProxySocketPool* http_proxy_pool =
244 new CapturePreconnectsHttpProxySocketPool(
245 session_deps.host_resolver.get(),
246 session_deps.cert_verifier.get());
247 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
248 CapturePreconnectsSSLSocketPool* ssl_conn_pool =
249 new CapturePreconnectsSSLSocketPool(
250 session_deps.host_resolver.get(),
251 session_deps.cert_verifier.get());
252 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
253 PreconnectHelper(kTests[i], session);
254 if (kTests[i].ssl)
255 EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams());
256 else
257 EXPECT_EQ(kTests[i].num_streams, http_proxy_pool->last_num_streams());
258 }
259 }
260
TEST(HttpStreamFactoryTest,PreconnectSocksProxy)261 TEST(HttpStreamFactoryTest, PreconnectSocksProxy) {
262 for (size_t i = 0; i < arraysize(kTests); ++i) {
263 SessionDependencies session_deps(
264 ProxyService::CreateFixed("socks4://socks_proxy:1080"));
265 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
266 HttpNetworkSessionPeer peer(session);
267 HostPortPair proxy_host("socks_proxy", 1080);
268 CapturePreconnectsSOCKSSocketPool* socks_proxy_pool =
269 new CapturePreconnectsSOCKSSocketPool(
270 session_deps.host_resolver.get(),
271 session_deps.cert_verifier.get());
272 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_proxy_pool);
273 CapturePreconnectsSSLSocketPool* ssl_conn_pool =
274 new CapturePreconnectsSSLSocketPool(
275 session_deps.host_resolver.get(),
276 session_deps.cert_verifier.get());
277 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
278 PreconnectHelper(kTests[i], session);
279 if (kTests[i].ssl)
280 EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams());
281 else
282 EXPECT_EQ(kTests[i].num_streams, socks_proxy_pool->last_num_streams());
283 }
284 }
285
TEST(HttpStreamFactoryTest,PreconnectDirectWithExistingSpdySession)286 TEST(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) {
287 for (size_t i = 0; i < arraysize(kTests); ++i) {
288 SessionDependencies session_deps(ProxyService::CreateDirect());
289 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
290 HttpNetworkSessionPeer peer(session);
291
292 // Set an existing SpdySession in the pool.
293 HostPortPair host_port_pair("www.google.com", 443);
294 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
295 scoped_refptr<SpdySession> spdy_session =
296 session->spdy_session_pool()->Get(pair, BoundNetLog());
297
298 CapturePreconnectsTransportSocketPool* transport_conn_pool =
299 new CapturePreconnectsTransportSocketPool(
300 session_deps.host_resolver.get(),
301 session_deps.cert_verifier.get());
302 peer.SetTransportSocketPool(transport_conn_pool);
303 CapturePreconnectsSSLSocketPool* ssl_conn_pool =
304 new CapturePreconnectsSSLSocketPool(
305 session_deps.host_resolver.get(),
306 session_deps.cert_verifier.get());
307 peer.SetSSLSocketPool(ssl_conn_pool);
308 PreconnectHelper(kTests[i], session);
309 // We shouldn't be preconnecting if we have an existing session, which is
310 // the case for https://www.google.com.
311 if (kTests[i].ssl)
312 EXPECT_EQ(-1, ssl_conn_pool->last_num_streams());
313 else
314 EXPECT_EQ(kTests[i].num_streams, transport_conn_pool->last_num_streams());
315 }
316 }
317
318 } // namespace
319
320 } // namespace net
321