Move android_app_version_* into an inner variables dict.
[chromium-blink-merge.git] / net / http / http_proxy_client_socket_pool_unittest.cc
blob7d1e432f8044456c22110d099be30200e5d17fc5
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.
5 #include "net/http/http_proxy_client_socket_pool.h"
7 #include "base/callback.h"
8 #include "base/compiler_specific.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "net/base/net_errors.h"
12 #include "net/base/proxy_delegate.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/http/http_network_session.h"
15 #include "net/http/http_proxy_client_socket.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/socket/client_socket_handle.h"
18 #include "net/socket/next_proto.h"
19 #include "net/socket/socket_test_util.h"
20 #include "net/spdy/spdy_protocol.h"
21 #include "net/spdy/spdy_test_util_common.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 namespace net {
26 namespace {
28 const int kMaxSockets = 32;
29 const int kMaxSocketsPerGroup = 6;
30 const char * const kAuthHeaders[] = {
31 "proxy-authorization", "Basic Zm9vOmJhcg=="
33 const int kAuthHeadersSize = arraysize(kAuthHeaders) / 2;
35 enum HttpProxyType {
36 HTTP,
37 HTTPS,
38 SPDY
41 struct HttpProxyClientSocketPoolTestParams {
42 HttpProxyClientSocketPoolTestParams()
43 : proxy_type(HTTP),
44 protocol(kProtoSPDY31) {}
46 HttpProxyClientSocketPoolTestParams(
47 HttpProxyType proxy_type,
48 NextProto protocol)
49 : proxy_type(proxy_type),
50 protocol(protocol) {}
52 HttpProxyType proxy_type;
53 NextProto protocol;
56 typedef ::testing::TestWithParam<HttpProxyType> TestWithHttpParam;
58 const char kHttpProxyHost[] = "httpproxy.example.com";
59 const char kHttpsProxyHost[] = "httpsproxy.example.com";
61 class TestProxyDelegate : public ProxyDelegate {
62 public:
63 TestProxyDelegate()
64 : on_before_tunnel_request_called_(false),
65 on_tunnel_request_completed_called_(false),
66 on_tunnel_headers_received_called_(false) {
69 ~TestProxyDelegate() override {}
71 bool on_before_tunnel_request_called() const {
72 return on_before_tunnel_request_called_;
75 bool on_tunnel_request_completed_called() const {
76 return on_tunnel_request_completed_called_;
79 bool on_tunnel_headers_received_called() const {
80 return on_tunnel_headers_received_called_;
83 void VerifyOnTunnelRequestCompleted(const std::string& endpoint,
84 const std::string& proxy_server) const {
85 EXPECT_TRUE(on_tunnel_request_completed_called_);
86 EXPECT_TRUE(HostPortPair::FromString(endpoint).Equals(
87 on_tunnel_request_completed_endpoint_));
88 EXPECT_TRUE(HostPortPair::FromString(proxy_server).Equals(
89 on_tunnel_request_completed_proxy_server_));
92 void VerifyOnTunnelHeadersReceived(const std::string& origin,
93 const std::string& proxy_server,
94 const std::string& status_line) const {
95 EXPECT_TRUE(on_tunnel_headers_received_called_);
96 EXPECT_TRUE(HostPortPair::FromString(origin).Equals(
97 on_tunnel_headers_received_origin_));
98 EXPECT_TRUE(HostPortPair::FromString(proxy_server).Equals(
99 on_tunnel_headers_received_proxy_server_));
100 EXPECT_EQ(status_line, on_tunnel_headers_received_status_line_);
103 // ProxyDelegate:
104 void OnResolveProxy(const GURL& url,
105 int load_flags,
106 const ProxyService& proxy_service,
107 ProxyInfo* result) override {}
109 void OnTunnelConnectCompleted(const HostPortPair& endpoint,
110 const HostPortPair& proxy_server,
111 int net_error) override {
112 on_tunnel_request_completed_called_ = true;
113 on_tunnel_request_completed_endpoint_ = endpoint;
114 on_tunnel_request_completed_proxy_server_ = proxy_server;
117 void OnFallback(const ProxyServer& bad_proxy, int net_error) override {}
119 void OnBeforeSendHeaders(URLRequest* request,
120 const ProxyInfo& proxy_info,
121 HttpRequestHeaders* headers) override {}
123 void OnBeforeTunnelRequest(const net::HostPortPair& proxy_server,
124 net::HttpRequestHeaders* extra_headers) override {
125 on_before_tunnel_request_called_ = true;
126 if (extra_headers) {
127 extra_headers->SetHeader("Foo", proxy_server.ToString());
131 void OnTunnelHeadersReceived(
132 const net::HostPortPair& origin,
133 const net::HostPortPair& proxy_server,
134 const net::HttpResponseHeaders& response_headers) override {
135 on_tunnel_headers_received_called_ = true;
136 on_tunnel_headers_received_origin_ = origin;
137 on_tunnel_headers_received_proxy_server_ = proxy_server;
138 on_tunnel_headers_received_status_line_ = response_headers.GetStatusLine();
141 private:
142 bool on_before_tunnel_request_called_;
143 bool on_tunnel_request_completed_called_;
144 bool on_tunnel_headers_received_called_;
145 HostPortPair on_tunnel_request_completed_endpoint_;
146 HostPortPair on_tunnel_request_completed_proxy_server_;
147 HostPortPair on_tunnel_headers_received_origin_;
148 HostPortPair on_tunnel_headers_received_proxy_server_;
149 std::string on_tunnel_headers_received_status_line_;
153 class HttpProxyClientSocketPoolTest
154 : public ::testing::TestWithParam<HttpProxyClientSocketPoolTestParams> {
155 protected:
156 HttpProxyClientSocketPoolTest()
157 : session_deps_(GetParam().protocol),
158 transport_socket_pool_(
159 kMaxSockets,
160 kMaxSocketsPerGroup,
161 session_deps_.deterministic_socket_factory.get()),
162 ssl_socket_pool_(kMaxSockets,
163 kMaxSocketsPerGroup,
164 session_deps_.cert_verifier.get(),
165 NULL /* channel_id_store */,
166 NULL /* transport_security_state */,
167 NULL /* cert_transparency_verifier */,
168 NULL /* cert_policy_enforcer */,
169 std::string() /* ssl_session_cache_shard */,
170 session_deps_.deterministic_socket_factory.get(),
171 &transport_socket_pool_,
172 NULL,
173 NULL,
174 session_deps_.ssl_config_service.get(),
175 BoundNetLog().net_log()),
176 session_(CreateNetworkSession()),
177 spdy_util_(GetParam().protocol),
178 pool_(kMaxSockets,
179 kMaxSocketsPerGroup,
180 &transport_socket_pool_,
181 &ssl_socket_pool_,
182 NULL) {}
184 virtual ~HttpProxyClientSocketPoolTest() {
187 void AddAuthToCache() {
188 const base::string16 kFoo(base::ASCIIToUTF16("foo"));
189 const base::string16 kBar(base::ASCIIToUTF16("bar"));
190 GURL proxy_url(GetParam().proxy_type == HTTP ?
191 (std::string("http://") + kHttpProxyHost) :
192 (std::string("https://") + kHttpsProxyHost));
193 session_->http_auth_cache()->Add(proxy_url,
194 "MyRealm1",
195 HttpAuth::AUTH_SCHEME_BASIC,
196 "Basic realm=MyRealm1",
197 AuthCredentials(kFoo, kBar),
198 "/");
201 scoped_refptr<TransportSocketParams> CreateHttpProxyParams() const {
202 if (GetParam().proxy_type != HTTP)
203 return NULL;
204 return new TransportSocketParams(
205 HostPortPair(kHttpProxyHost, 80),
206 false,
207 false,
208 OnHostResolutionCallback(),
209 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT);
212 scoped_refptr<SSLSocketParams> CreateHttpsProxyParams() const {
213 if (GetParam().proxy_type == HTTP)
214 return NULL;
215 return new SSLSocketParams(
216 new TransportSocketParams(
217 HostPortPair(kHttpsProxyHost, 443),
218 false,
219 false,
220 OnHostResolutionCallback(),
221 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT),
222 NULL,
223 NULL,
224 HostPortPair(kHttpsProxyHost, 443),
225 SSLConfig(),
226 PRIVACY_MODE_DISABLED,
228 false,
229 false);
232 // Returns the a correctly constructed HttpProxyParms
233 // for the HTTP or HTTPS proxy.
234 scoped_refptr<HttpProxySocketParams> CreateParams(
235 bool tunnel,
236 ProxyDelegate* proxy_delegate) {
237 return scoped_refptr<HttpProxySocketParams>(new HttpProxySocketParams(
238 CreateHttpProxyParams(),
239 CreateHttpsProxyParams(),
240 GURL(tunnel ? "https://www.google.com/" : "http://www.google.com"),
241 std::string(),
242 HostPortPair("www.google.com", tunnel ? 443 : 80),
243 session_->http_auth_cache(),
244 session_->http_auth_handler_factory(),
245 session_->spdy_session_pool(),
246 tunnel,
247 proxy_delegate));
250 scoped_refptr<HttpProxySocketParams> CreateTunnelParams(
251 ProxyDelegate* proxy_delegate) {
252 return CreateParams(true, proxy_delegate);
255 scoped_refptr<HttpProxySocketParams> CreateNoTunnelParams(
256 ProxyDelegate* proxy_delegate) {
257 return CreateParams(false, proxy_delegate);
260 DeterministicMockClientSocketFactory* socket_factory() {
261 return session_deps_.deterministic_socket_factory.get();
264 void Initialize(MockRead* reads, size_t reads_count,
265 MockWrite* writes, size_t writes_count,
266 MockRead* spdy_reads, size_t spdy_reads_count,
267 MockWrite* spdy_writes, size_t spdy_writes_count) {
268 if (GetParam().proxy_type == SPDY) {
269 data_.reset(new DeterministicSocketData(spdy_reads, spdy_reads_count,
270 spdy_writes, spdy_writes_count));
271 } else {
272 data_.reset(new DeterministicSocketData(reads, reads_count, writes,
273 writes_count));
276 data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
277 data_->StopAfter(2); // Request / Response
279 socket_factory()->AddSocketDataProvider(data_.get());
281 if (GetParam().proxy_type != HTTP) {
282 ssl_data_.reset(new SSLSocketDataProvider(SYNCHRONOUS, OK));
283 if (GetParam().proxy_type == SPDY) {
284 InitializeSpdySsl();
286 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
290 void InitializeSpdySsl() {
291 ssl_data_->SetNextProto(GetParam().protocol);
294 HttpNetworkSession* CreateNetworkSession() {
295 return SpdySessionDependencies::SpdyCreateSessionDeterministic(
296 &session_deps_);
299 RequestPriority GetLastTransportRequestPriority() const {
300 return transport_socket_pool_.last_request_priority();
303 private:
304 SpdySessionDependencies session_deps_;
306 MockTransportClientSocketPool transport_socket_pool_;
307 MockHostResolver host_resolver_;
308 scoped_ptr<CertVerifier> cert_verifier_;
309 SSLClientSocketPool ssl_socket_pool_;
311 const scoped_refptr<HttpNetworkSession> session_;
313 protected:
314 SpdyTestUtil spdy_util_;
315 scoped_ptr<SSLSocketDataProvider> ssl_data_;
316 scoped_ptr<DeterministicSocketData> data_;
317 HttpProxyClientSocketPool pool_;
318 ClientSocketHandle handle_;
319 TestCompletionCallback callback_;
322 //-----------------------------------------------------------------------------
323 // All tests are run with three different proxy types: HTTP, HTTPS (non-SPDY)
324 // and SPDY.
326 // TODO(akalin): Use ::testing::Combine() when we are able to use
327 // <tr1/tuple>.
328 INSTANTIATE_TEST_CASE_P(
329 HttpProxyClientSocketPoolTests,
330 HttpProxyClientSocketPoolTest,
331 ::testing::Values(
332 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY31),
333 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY31),
334 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY31),
335 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY4_14),
336 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY4_14),
337 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY4_14),
338 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY4),
339 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY4),
340 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY4)));
342 TEST_P(HttpProxyClientSocketPoolTest, NoTunnel) {
343 Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
345 scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
346 int rv = handle_.Init("a", CreateNoTunnelParams(proxy_delegate.get()), LOW,
347 CompletionCallback(), &pool_, BoundNetLog());
348 EXPECT_EQ(OK, rv);
349 EXPECT_TRUE(handle_.is_initialized());
350 ASSERT_TRUE(handle_.socket());
351 HttpProxyClientSocket* tunnel_socket =
352 static_cast<HttpProxyClientSocket*>(handle_.socket());
353 EXPECT_TRUE(tunnel_socket->IsConnected());
354 EXPECT_FALSE(proxy_delegate->on_before_tunnel_request_called());
355 EXPECT_FALSE(proxy_delegate->on_tunnel_headers_received_called());
356 EXPECT_TRUE(proxy_delegate->on_tunnel_request_completed_called());
359 // Make sure that HttpProxyConnectJob passes on its priority to its
360 // (non-SSL) socket request on Init.
361 TEST_P(HttpProxyClientSocketPoolTest, SetSocketRequestPriorityOnInit) {
362 Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
363 EXPECT_EQ(OK,
364 handle_.Init("a", CreateNoTunnelParams(NULL), HIGHEST,
365 CompletionCallback(), &pool_, BoundNetLog()));
366 EXPECT_EQ(HIGHEST, GetLastTransportRequestPriority());
369 TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
370 MockWrite writes[] = {
371 MockWrite(ASYNC, 0, "CONNECT www.google.com:443 HTTP/1.1\r\n"
372 "Host: www.google.com\r\n"
373 "Proxy-Connection: keep-alive\r\n\r\n"),
375 MockRead reads[] = {
376 // No credentials.
377 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
378 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
379 MockRead(ASYNC, 3, "Content-Length: 10\r\n\r\n"),
380 MockRead(ASYNC, 4, "0123456789"),
382 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
383 NULL, 0, 1, LOW, HostPortPair("www.google.com", 443)));
384 scoped_ptr<SpdyFrame> rst(
385 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
386 MockWrite spdy_writes[] = {
387 CreateMockWrite(*req, 0, ASYNC),
388 CreateMockWrite(*rst, 2, ASYNC),
390 SpdyHeaderBlock resp_block;
391 resp_block[spdy_util_.GetStatusKey()] = "407";
392 resp_block["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
393 spdy_util_.MaybeAddVersionHeader(&resp_block);
395 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, resp_block));
396 MockRead spdy_reads[] = {
397 CreateMockRead(*resp, 1, ASYNC),
398 MockRead(ASYNC, 0, 3)
401 Initialize(reads, arraysize(reads), writes, arraysize(writes),
402 spdy_reads, arraysize(spdy_reads), spdy_writes,
403 arraysize(spdy_writes));
405 data_->StopAfter(4);
406 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
407 callback_.callback(), &pool_, BoundNetLog());
408 EXPECT_EQ(ERR_IO_PENDING, rv);
409 EXPECT_FALSE(handle_.is_initialized());
410 EXPECT_FALSE(handle_.socket());
412 data_->RunFor(GetParam().proxy_type == SPDY ? 2 : 4);
413 rv = callback_.WaitForResult();
414 EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, rv);
415 EXPECT_TRUE(handle_.is_initialized());
416 ASSERT_TRUE(handle_.socket());
417 ProxyClientSocket* tunnel_socket =
418 static_cast<ProxyClientSocket*>(handle_.socket());
419 if (GetParam().proxy_type == SPDY) {
420 EXPECT_TRUE(tunnel_socket->IsConnected());
421 EXPECT_TRUE(tunnel_socket->IsUsingSpdy());
422 } else {
423 EXPECT_FALSE(tunnel_socket->IsConnected());
424 EXPECT_FALSE(tunnel_socket->IsUsingSpdy());
428 TEST_P(HttpProxyClientSocketPoolTest, HaveAuth) {
429 // It's pretty much impossible to make the SPDY case behave synchronously
430 // so we skip this test for SPDY
431 if (GetParam().proxy_type == SPDY)
432 return;
433 std::string proxy_host_port =
434 GetParam().proxy_type == HTTP ?
435 (kHttpProxyHost + std::string(":80")) :
436 (kHttpsProxyHost + std::string(":443"));
437 std::string request =
438 "CONNECT www.google.com:443 HTTP/1.1\r\n"
439 "Host: www.google.com\r\n"
440 "Proxy-Connection: keep-alive\r\n"
441 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
442 "Foo: " + proxy_host_port + "\r\n\r\n";
443 MockWrite writes[] = {
444 MockWrite(SYNCHRONOUS, 0, request.c_str()),
446 MockRead reads[] = {
447 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
450 Initialize(reads, arraysize(reads), writes, arraysize(writes), NULL, 0,
451 NULL, 0);
452 AddAuthToCache();
454 scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
455 int rv = handle_.Init("a", CreateTunnelParams(proxy_delegate.get()), LOW,
456 callback_.callback(), &pool_, BoundNetLog());
457 EXPECT_EQ(OK, rv);
458 EXPECT_TRUE(handle_.is_initialized());
459 ASSERT_TRUE(handle_.socket());
460 HttpProxyClientSocket* tunnel_socket =
461 static_cast<HttpProxyClientSocket*>(handle_.socket());
462 EXPECT_TRUE(tunnel_socket->IsConnected());
463 proxy_delegate->VerifyOnTunnelHeadersReceived(
464 "www.google.com:443",
465 proxy_host_port.c_str(),
466 "HTTP/1.1 200 Connection Established");
467 proxy_delegate->VerifyOnTunnelRequestCompleted(
468 "www.google.com:443",
469 proxy_host_port.c_str());
472 TEST_P(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
473 std::string proxy_host_port =
474 GetParam().proxy_type == HTTP ?
475 (kHttpProxyHost + std::string(":80")) :
476 (kHttpsProxyHost + std::string(":443"));
477 std::string request =
478 "CONNECT www.google.com:443 HTTP/1.1\r\n"
479 "Host: www.google.com\r\n"
480 "Proxy-Connection: keep-alive\r\n"
481 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
482 "Foo: " + proxy_host_port + "\r\n\r\n";
483 MockWrite writes[] = {
484 MockWrite(ASYNC, 0, request.c_str()),
486 MockRead reads[] = {
487 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
490 scoped_ptr<SpdyFrame> req(
491 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
492 HostPortPair("www.google.com", 443)));
493 MockWrite spdy_writes[] = {
494 CreateMockWrite(*req, 0, ASYNC)
496 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
497 MockRead spdy_reads[] = {
498 CreateMockRead(*resp, 1, ASYNC),
499 MockRead(ASYNC, 0, 2)
502 Initialize(reads, arraysize(reads), writes, arraysize(writes),
503 spdy_reads, arraysize(spdy_reads), spdy_writes,
504 arraysize(spdy_writes));
505 AddAuthToCache();
507 scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
508 int rv = handle_.Init("a", CreateTunnelParams(proxy_delegate.get()), LOW,
509 callback_.callback(), &pool_, BoundNetLog());
510 EXPECT_EQ(ERR_IO_PENDING, rv);
511 EXPECT_FALSE(handle_.is_initialized());
512 EXPECT_FALSE(handle_.socket());
514 data_->RunFor(2);
515 EXPECT_EQ(OK, callback_.WaitForResult());
516 EXPECT_TRUE(handle_.is_initialized());
517 ASSERT_TRUE(handle_.socket());
518 EXPECT_TRUE(handle_.socket()->IsConnected());
519 proxy_delegate->VerifyOnTunnelRequestCompleted(
520 "www.google.com:443",
521 proxy_host_port.c_str());
524 // Make sure that HttpProxyConnectJob passes on its priority to its
525 // SPDY session's socket request on Init (if applicable).
526 TEST_P(HttpProxyClientSocketPoolTest,
527 SetSpdySessionSocketRequestPriorityOnInit) {
528 if (GetParam().proxy_type != SPDY)
529 return;
531 scoped_ptr<SpdyFrame> req(
532 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, MEDIUM,
533 HostPortPair("www.google.com", 443)));
534 MockWrite spdy_writes[] = {
535 CreateMockWrite(*req, 0, ASYNC)
537 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
538 MockRead spdy_reads[] = {
539 CreateMockRead(*resp, 1, ASYNC),
540 MockRead(ASYNC, 0, 2)
543 Initialize(NULL, 0, NULL, 0,
544 spdy_reads, arraysize(spdy_reads),
545 spdy_writes, arraysize(spdy_writes));
546 AddAuthToCache();
548 EXPECT_EQ(ERR_IO_PENDING,
549 handle_.Init("a", CreateTunnelParams(NULL), MEDIUM,
550 callback_.callback(), &pool_, BoundNetLog()));
551 EXPECT_EQ(MEDIUM, GetLastTransportRequestPriority());
553 data_->RunFor(2);
554 EXPECT_EQ(OK, callback_.WaitForResult());
557 TEST_P(HttpProxyClientSocketPoolTest, TCPError) {
558 if (GetParam().proxy_type == SPDY) return;
559 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
560 data_->set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_CLOSED));
562 socket_factory()->AddSocketDataProvider(data_.get());
564 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
565 callback_.callback(), &pool_, BoundNetLog());
566 EXPECT_EQ(ERR_IO_PENDING, rv);
567 EXPECT_FALSE(handle_.is_initialized());
568 EXPECT_FALSE(handle_.socket());
570 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, callback_.WaitForResult());
572 EXPECT_FALSE(handle_.is_initialized());
573 EXPECT_FALSE(handle_.socket());
576 TEST_P(HttpProxyClientSocketPoolTest, SSLError) {
577 if (GetParam().proxy_type == HTTP) return;
578 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
579 data_->set_connect_data(MockConnect(ASYNC, OK));
580 socket_factory()->AddSocketDataProvider(data_.get());
582 ssl_data_.reset(new SSLSocketDataProvider(ASYNC,
583 ERR_CERT_AUTHORITY_INVALID));
584 if (GetParam().proxy_type == SPDY) {
585 InitializeSpdySsl();
587 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
589 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
590 callback_.callback(), &pool_, BoundNetLog());
591 EXPECT_EQ(ERR_IO_PENDING, rv);
592 EXPECT_FALSE(handle_.is_initialized());
593 EXPECT_FALSE(handle_.socket());
595 EXPECT_EQ(ERR_PROXY_CERTIFICATE_INVALID, callback_.WaitForResult());
597 EXPECT_FALSE(handle_.is_initialized());
598 EXPECT_FALSE(handle_.socket());
601 TEST_P(HttpProxyClientSocketPoolTest, SslClientAuth) {
602 if (GetParam().proxy_type == HTTP) return;
603 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
604 data_->set_connect_data(MockConnect(ASYNC, OK));
605 socket_factory()->AddSocketDataProvider(data_.get());
607 ssl_data_.reset(new SSLSocketDataProvider(ASYNC,
608 ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
609 if (GetParam().proxy_type == SPDY) {
610 InitializeSpdySsl();
612 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
614 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
615 callback_.callback(), &pool_, BoundNetLog());
616 EXPECT_EQ(ERR_IO_PENDING, rv);
617 EXPECT_FALSE(handle_.is_initialized());
618 EXPECT_FALSE(handle_.socket());
620 EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, callback_.WaitForResult());
622 EXPECT_FALSE(handle_.is_initialized());
623 EXPECT_FALSE(handle_.socket());
626 TEST_P(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
627 MockWrite writes[] = {
628 MockWrite(ASYNC, 0,
629 "CONNECT www.google.com:443 HTTP/1.1\r\n"
630 "Host: www.google.com\r\n"
631 "Proxy-Connection: keep-alive\r\n"
632 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
634 MockRead reads[] = {
635 MockRead(ASYNC, 1, "HTTP/1.1 200 Conn"),
636 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 2),
638 scoped_ptr<SpdyFrame> req(
639 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
640 HostPortPair("www.google.com", 443)));
641 MockWrite spdy_writes[] = {
642 CreateMockWrite(*req, 0, ASYNC)
644 MockRead spdy_reads[] = {
645 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 1),
648 Initialize(reads, arraysize(reads), writes, arraysize(writes),
649 spdy_reads, arraysize(spdy_reads), spdy_writes,
650 arraysize(spdy_writes));
651 AddAuthToCache();
653 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
654 callback_.callback(), &pool_, BoundNetLog());
655 EXPECT_EQ(ERR_IO_PENDING, rv);
656 EXPECT_FALSE(handle_.is_initialized());
657 EXPECT_FALSE(handle_.socket());
659 data_->RunFor(3);
660 if (GetParam().proxy_type == SPDY) {
661 // SPDY cannot process a headers block unless it's complete and so it
662 // returns ERR_CONNECTION_CLOSED in this case.
663 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback_.WaitForResult());
664 } else {
665 EXPECT_EQ(ERR_RESPONSE_HEADERS_TRUNCATED, callback_.WaitForResult());
667 EXPECT_FALSE(handle_.is_initialized());
668 EXPECT_FALSE(handle_.socket());
671 TEST_P(HttpProxyClientSocketPoolTest, Tunnel1xxResponse) {
672 // Tests that 1xx responses are rejected for a CONNECT request.
673 if (GetParam().proxy_type == SPDY) {
674 // SPDY doesn't have 1xx responses.
675 return;
678 MockWrite writes[] = {
679 MockWrite(ASYNC, 0,
680 "CONNECT www.google.com:443 HTTP/1.1\r\n"
681 "Host: www.google.com\r\n"
682 "Proxy-Connection: keep-alive\r\n\r\n"),
684 MockRead reads[] = {
685 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
686 MockRead(ASYNC, 2, "HTTP/1.1 200 Connection Established\r\n\r\n"),
689 Initialize(reads, arraysize(reads), writes, arraysize(writes),
690 NULL, 0, NULL, 0);
692 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
693 callback_.callback(), &pool_, BoundNetLog());
694 EXPECT_EQ(ERR_IO_PENDING, rv);
695 EXPECT_FALSE(handle_.is_initialized());
696 EXPECT_FALSE(handle_.socket());
698 data_->RunFor(2);
699 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult());
702 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupError) {
703 MockWrite writes[] = {
704 MockWrite(ASYNC, 0,
705 "CONNECT www.google.com:443 HTTP/1.1\r\n"
706 "Host: www.google.com\r\n"
707 "Proxy-Connection: keep-alive\r\n"
708 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
710 MockRead reads[] = {
711 MockRead(ASYNC, 1, "HTTP/1.1 304 Not Modified\r\n\r\n"),
713 scoped_ptr<SpdyFrame> req(
714 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
715 HostPortPair("www.google.com", 443)));
716 scoped_ptr<SpdyFrame> rst(
717 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
718 MockWrite spdy_writes[] = {
719 CreateMockWrite(*req, 0, ASYNC),
720 CreateMockWrite(*rst, 2, ASYNC),
722 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
723 MockRead spdy_reads[] = {
724 CreateMockRead(*resp, 1, ASYNC),
725 MockRead(ASYNC, 0, 3),
728 Initialize(reads, arraysize(reads), writes, arraysize(writes),
729 spdy_reads, arraysize(spdy_reads), spdy_writes,
730 arraysize(spdy_writes));
731 AddAuthToCache();
733 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
734 callback_.callback(), &pool_, BoundNetLog());
735 EXPECT_EQ(ERR_IO_PENDING, rv);
736 EXPECT_FALSE(handle_.is_initialized());
737 EXPECT_FALSE(handle_.socket());
739 data_->RunFor(2);
741 rv = callback_.WaitForResult();
742 // All Proxy CONNECT responses are not trustworthy
743 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
744 EXPECT_FALSE(handle_.is_initialized());
745 EXPECT_FALSE(handle_.socket());
748 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupRedirect) {
749 const std::string redirectTarget = "https://foo.google.com/";
751 const std::string responseText = "HTTP/1.1 302 Found\r\n"
752 "Location: " + redirectTarget + "\r\n"
753 "Set-Cookie: foo=bar\r\n"
754 "\r\n";
755 MockWrite writes[] = {
756 MockWrite(ASYNC, 0,
757 "CONNECT www.google.com:443 HTTP/1.1\r\n"
758 "Host: www.google.com\r\n"
759 "Proxy-Connection: keep-alive\r\n"
760 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
762 MockRead reads[] = {
763 MockRead(ASYNC, 1, responseText.c_str()),
765 scoped_ptr<SpdyFrame> req(
766 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
767 HostPortPair("www.google.com", 443)));
768 scoped_ptr<SpdyFrame> rst(
769 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
771 MockWrite spdy_writes[] = {
772 CreateMockWrite(*req, 0, ASYNC),
773 CreateMockWrite(*rst, 3, ASYNC),
776 const char* const responseHeaders[] = {
777 "location", redirectTarget.c_str(),
778 "set-cookie", "foo=bar",
780 const int responseHeadersSize = arraysize(responseHeaders) / 2;
781 scoped_ptr<SpdyFrame> resp(
782 spdy_util_.ConstructSpdySynReplyError(
783 "302 Found",
784 responseHeaders, responseHeadersSize,
785 1));
786 MockRead spdy_reads[] = {
787 CreateMockRead(*resp, 1, ASYNC),
788 MockRead(ASYNC, 0, 2),
791 Initialize(reads, arraysize(reads), writes, arraysize(writes),
792 spdy_reads, arraysize(spdy_reads), spdy_writes,
793 arraysize(spdy_writes));
794 AddAuthToCache();
796 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
797 callback_.callback(), &pool_, BoundNetLog());
798 EXPECT_EQ(ERR_IO_PENDING, rv);
799 EXPECT_FALSE(handle_.is_initialized());
800 EXPECT_FALSE(handle_.socket());
802 data_->RunFor(2);
804 rv = callback_.WaitForResult();
806 if (GetParam().proxy_type == HTTP) {
807 // We don't trust 302 responses to CONNECT from HTTP proxies.
808 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
809 EXPECT_FALSE(handle_.is_initialized());
810 EXPECT_FALSE(handle_.socket());
811 } else {
812 // Expect ProxyClientSocket to return the proxy's response, sanitized.
813 EXPECT_EQ(ERR_HTTPS_PROXY_TUNNEL_RESPONSE, rv);
814 EXPECT_TRUE(handle_.is_initialized());
815 ASSERT_TRUE(handle_.socket());
817 const ProxyClientSocket* tunnel_socket =
818 static_cast<ProxyClientSocket*>(handle_.socket());
819 const HttpResponseInfo* response = tunnel_socket->GetConnectResponseInfo();
820 const HttpResponseHeaders* headers = response->headers.get();
822 // Make sure Set-Cookie header was stripped.
823 EXPECT_FALSE(headers->HasHeader("set-cookie"));
825 // Make sure Content-Length: 0 header was added.
826 EXPECT_TRUE(headers->HasHeaderValue("content-length", "0"));
828 // Make sure Location header was included and correct.
829 std::string location;
830 EXPECT_TRUE(headers->IsRedirect(&location));
831 EXPECT_EQ(location, redirectTarget);
835 // It would be nice to also test the timeouts in HttpProxyClientSocketPool.
837 } // namespace
839 } // namespace net