Sort unlaunched apps on app list start page by apps grid order.
[chromium-blink-merge.git] / net / http / http_proxy_client_socket_pool_unittest.cc
blob62c50c024d26c805a5ce08f942aa0f808adbdc48
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/client_socket_pool_histograms.h"
19 #include "net/socket/next_proto.h"
20 #include "net/socket/socket_test_util.h"
21 #include "net/spdy/spdy_protocol.h"
22 #include "net/spdy/spdy_test_util_common.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 namespace net {
27 namespace {
29 const int kMaxSockets = 32;
30 const int kMaxSocketsPerGroup = 6;
31 const char * const kAuthHeaders[] = {
32 "proxy-authorization", "Basic Zm9vOmJhcg=="
34 const int kAuthHeadersSize = arraysize(kAuthHeaders) / 2;
36 enum HttpProxyType {
37 HTTP,
38 HTTPS,
39 SPDY
42 struct HttpProxyClientSocketPoolTestParams {
43 HttpProxyClientSocketPoolTestParams()
44 : proxy_type(HTTP),
45 protocol(kProtoSPDY31) {}
47 HttpProxyClientSocketPoolTestParams(
48 HttpProxyType proxy_type,
49 NextProto protocol)
50 : proxy_type(proxy_type),
51 protocol(protocol) {}
53 HttpProxyType proxy_type;
54 NextProto protocol;
57 typedef ::testing::TestWithParam<HttpProxyType> TestWithHttpParam;
59 const char kHttpProxyHost[] = "httpproxy.example.com";
60 const char kHttpsProxyHost[] = "httpsproxy.example.com";
62 class TestProxyDelegate : public ProxyDelegate {
63 public:
64 TestProxyDelegate()
65 : on_before_tunnel_request_called_(false),
66 on_tunnel_request_completed_called_(false),
67 on_tunnel_headers_received_called_(false) {
70 ~TestProxyDelegate() override {}
72 bool on_before_tunnel_request_called() const {
73 return on_before_tunnel_request_called_;
76 bool on_tunnel_request_completed_called() const {
77 return on_tunnel_request_completed_called_;
80 bool on_tunnel_headers_received_called() const {
81 return on_tunnel_headers_received_called_;
84 void VerifyOnTunnelRequestCompleted(const std::string& endpoint,
85 const std::string& proxy_server) const {
86 EXPECT_TRUE(on_tunnel_request_completed_called_);
87 EXPECT_TRUE(HostPortPair::FromString(endpoint).Equals(
88 on_tunnel_request_completed_endpoint_));
89 EXPECT_TRUE(HostPortPair::FromString(proxy_server).Equals(
90 on_tunnel_request_completed_proxy_server_));
93 void VerifyOnTunnelHeadersReceived(const std::string& origin,
94 const std::string& proxy_server,
95 const std::string& status_line) const {
96 EXPECT_TRUE(on_tunnel_headers_received_called_);
97 EXPECT_TRUE(HostPortPair::FromString(origin).Equals(
98 on_tunnel_headers_received_origin_));
99 EXPECT_TRUE(HostPortPair::FromString(proxy_server).Equals(
100 on_tunnel_headers_received_proxy_server_));
101 EXPECT_EQ(status_line, on_tunnel_headers_received_status_line_);
104 // ProxyDelegate:
105 void OnResolveProxy(const GURL& url,
106 int load_flags,
107 const ProxyService& proxy_service,
108 ProxyInfo* result) override {}
110 void OnTunnelConnectCompleted(const HostPortPair& endpoint,
111 const HostPortPair& proxy_server,
112 int net_error) override {
113 on_tunnel_request_completed_called_ = true;
114 on_tunnel_request_completed_endpoint_ = endpoint;
115 on_tunnel_request_completed_proxy_server_ = proxy_server;
118 void OnFallback(const ProxyServer& bad_proxy, int net_error) override {}
120 void OnBeforeSendHeaders(URLRequest* request,
121 const ProxyInfo& proxy_info,
122 HttpRequestHeaders* headers) override {}
124 void OnBeforeTunnelRequest(const net::HostPortPair& proxy_server,
125 net::HttpRequestHeaders* extra_headers) override {
126 on_before_tunnel_request_called_ = true;
127 if (extra_headers) {
128 extra_headers->SetHeader("Foo", proxy_server.ToString());
132 void OnTunnelHeadersReceived(
133 const net::HostPortPair& origin,
134 const net::HostPortPair& proxy_server,
135 const net::HttpResponseHeaders& response_headers) override {
136 on_tunnel_headers_received_called_ = true;
137 on_tunnel_headers_received_origin_ = origin;
138 on_tunnel_headers_received_proxy_server_ = proxy_server;
139 on_tunnel_headers_received_status_line_ = response_headers.GetStatusLine();
142 private:
143 bool on_before_tunnel_request_called_;
144 bool on_tunnel_request_completed_called_;
145 bool on_tunnel_headers_received_called_;
146 HostPortPair on_tunnel_request_completed_endpoint_;
147 HostPortPair on_tunnel_request_completed_proxy_server_;
148 HostPortPair on_tunnel_headers_received_origin_;
149 HostPortPair on_tunnel_headers_received_proxy_server_;
150 std::string on_tunnel_headers_received_status_line_;
154 class HttpProxyClientSocketPoolTest
155 : public ::testing::TestWithParam<HttpProxyClientSocketPoolTestParams> {
156 protected:
157 HttpProxyClientSocketPoolTest()
158 : session_deps_(GetParam().protocol),
159 tcp_histograms_("MockTCP"),
160 transport_socket_pool_(
161 kMaxSockets,
162 kMaxSocketsPerGroup,
163 &tcp_histograms_,
164 session_deps_.deterministic_socket_factory.get()),
165 ssl_histograms_("MockSSL"),
166 ssl_socket_pool_(kMaxSockets,
167 kMaxSocketsPerGroup,
168 &ssl_histograms_,
169 session_deps_.cert_verifier.get(),
170 NULL /* channel_id_store */,
171 NULL /* transport_security_state */,
172 NULL /* cert_transparency_verifier */,
173 NULL /* cert_policy_enforcer */,
174 std::string() /* ssl_session_cache_shard */,
175 session_deps_.deterministic_socket_factory.get(),
176 &transport_socket_pool_,
177 NULL,
178 NULL,
179 session_deps_.ssl_config_service.get(),
180 false,
181 BoundNetLog().net_log()),
182 session_(CreateNetworkSession()),
183 http_proxy_histograms_("HttpProxyUnitTest"),
184 spdy_util_(GetParam().protocol),
185 pool_(kMaxSockets,
186 kMaxSocketsPerGroup,
187 &http_proxy_histograms_,
188 &transport_socket_pool_,
189 &ssl_socket_pool_,
190 NULL) {}
192 virtual ~HttpProxyClientSocketPoolTest() {
195 void AddAuthToCache() {
196 const base::string16 kFoo(base::ASCIIToUTF16("foo"));
197 const base::string16 kBar(base::ASCIIToUTF16("bar"));
198 GURL proxy_url(GetParam().proxy_type == HTTP ?
199 (std::string("http://") + kHttpProxyHost) :
200 (std::string("https://") + kHttpsProxyHost));
201 session_->http_auth_cache()->Add(proxy_url,
202 "MyRealm1",
203 HttpAuth::AUTH_SCHEME_BASIC,
204 "Basic realm=MyRealm1",
205 AuthCredentials(kFoo, kBar),
206 "/");
209 scoped_refptr<TransportSocketParams> CreateHttpProxyParams() const {
210 if (GetParam().proxy_type != HTTP)
211 return NULL;
212 return new TransportSocketParams(
213 HostPortPair(kHttpProxyHost, 80),
214 false,
215 false,
216 OnHostResolutionCallback(),
217 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT);
220 scoped_refptr<SSLSocketParams> CreateHttpsProxyParams() const {
221 if (GetParam().proxy_type == HTTP)
222 return NULL;
223 return new SSLSocketParams(
224 new TransportSocketParams(
225 HostPortPair(kHttpsProxyHost, 443),
226 false,
227 false,
228 OnHostResolutionCallback(),
229 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT),
230 NULL,
231 NULL,
232 HostPortPair(kHttpsProxyHost, 443),
233 SSLConfig(),
234 PRIVACY_MODE_DISABLED,
236 false,
237 false);
240 // Returns the a correctly constructed HttpProxyParms
241 // for the HTTP or HTTPS proxy.
242 scoped_refptr<HttpProxySocketParams> CreateParams(
243 bool tunnel,
244 ProxyDelegate* proxy_delegate) {
245 return scoped_refptr<HttpProxySocketParams>(new HttpProxySocketParams(
246 CreateHttpProxyParams(),
247 CreateHttpsProxyParams(),
248 GURL(tunnel ? "https://www.google.com/" : "http://www.google.com"),
249 std::string(),
250 HostPortPair("www.google.com", tunnel ? 443 : 80),
251 session_->http_auth_cache(),
252 session_->http_auth_handler_factory(),
253 session_->spdy_session_pool(),
254 tunnel,
255 proxy_delegate));
258 scoped_refptr<HttpProxySocketParams> CreateTunnelParams(
259 ProxyDelegate* proxy_delegate) {
260 return CreateParams(true, proxy_delegate);
263 scoped_refptr<HttpProxySocketParams> CreateNoTunnelParams(
264 ProxyDelegate* proxy_delegate) {
265 return CreateParams(false, proxy_delegate);
268 DeterministicMockClientSocketFactory* socket_factory() {
269 return session_deps_.deterministic_socket_factory.get();
272 void Initialize(MockRead* reads, size_t reads_count,
273 MockWrite* writes, size_t writes_count,
274 MockRead* spdy_reads, size_t spdy_reads_count,
275 MockWrite* spdy_writes, size_t spdy_writes_count) {
276 if (GetParam().proxy_type == SPDY) {
277 data_.reset(new DeterministicSocketData(spdy_reads, spdy_reads_count,
278 spdy_writes, spdy_writes_count));
279 } else {
280 data_.reset(new DeterministicSocketData(reads, reads_count, writes,
281 writes_count));
284 data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
285 data_->StopAfter(2); // Request / Response
287 socket_factory()->AddSocketDataProvider(data_.get());
289 if (GetParam().proxy_type != HTTP) {
290 ssl_data_.reset(new SSLSocketDataProvider(SYNCHRONOUS, OK));
291 if (GetParam().proxy_type == SPDY) {
292 InitializeSpdySsl();
294 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
298 void InitializeSpdySsl() {
299 ssl_data_->SetNextProto(GetParam().protocol);
302 HttpNetworkSession* CreateNetworkSession() {
303 return SpdySessionDependencies::SpdyCreateSessionDeterministic(
304 &session_deps_);
307 RequestPriority GetLastTransportRequestPriority() const {
308 return transport_socket_pool_.last_request_priority();
311 private:
312 SpdySessionDependencies session_deps_;
314 ClientSocketPoolHistograms tcp_histograms_;
315 MockTransportClientSocketPool transport_socket_pool_;
316 ClientSocketPoolHistograms ssl_histograms_;
317 MockHostResolver host_resolver_;
318 scoped_ptr<CertVerifier> cert_verifier_;
319 SSLClientSocketPool ssl_socket_pool_;
321 const scoped_refptr<HttpNetworkSession> session_;
322 ClientSocketPoolHistograms http_proxy_histograms_;
324 protected:
325 SpdyTestUtil spdy_util_;
326 scoped_ptr<SSLSocketDataProvider> ssl_data_;
327 scoped_ptr<DeterministicSocketData> data_;
328 HttpProxyClientSocketPool pool_;
329 ClientSocketHandle handle_;
330 TestCompletionCallback callback_;
333 //-----------------------------------------------------------------------------
334 // All tests are run with three different proxy types: HTTP, HTTPS (non-SPDY)
335 // and SPDY.
337 // TODO(akalin): Use ::testing::Combine() when we are able to use
338 // <tr1/tuple>.
339 INSTANTIATE_TEST_CASE_P(
340 HttpProxyClientSocketPoolTests,
341 HttpProxyClientSocketPoolTest,
342 ::testing::Values(
343 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY31),
344 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY31),
345 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY31),
346 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY4_14),
347 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY4_14),
348 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY4_14),
349 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY4_15),
350 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY4_15),
351 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY4_15)));
353 TEST_P(HttpProxyClientSocketPoolTest, NoTunnel) {
354 Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
356 scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
357 int rv = handle_.Init("a", CreateNoTunnelParams(proxy_delegate.get()), LOW,
358 CompletionCallback(), &pool_, BoundNetLog());
359 EXPECT_EQ(OK, rv);
360 EXPECT_TRUE(handle_.is_initialized());
361 ASSERT_TRUE(handle_.socket());
362 HttpProxyClientSocket* tunnel_socket =
363 static_cast<HttpProxyClientSocket*>(handle_.socket());
364 EXPECT_TRUE(tunnel_socket->IsConnected());
365 EXPECT_FALSE(proxy_delegate->on_before_tunnel_request_called());
366 EXPECT_FALSE(proxy_delegate->on_tunnel_headers_received_called());
367 EXPECT_TRUE(proxy_delegate->on_tunnel_request_completed_called());
370 // Make sure that HttpProxyConnectJob passes on its priority to its
371 // (non-SSL) socket request on Init.
372 TEST_P(HttpProxyClientSocketPoolTest, SetSocketRequestPriorityOnInit) {
373 Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
374 EXPECT_EQ(OK,
375 handle_.Init("a", CreateNoTunnelParams(NULL), HIGHEST,
376 CompletionCallback(), &pool_, BoundNetLog()));
377 EXPECT_EQ(HIGHEST, GetLastTransportRequestPriority());
380 TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
381 MockWrite writes[] = {
382 MockWrite(ASYNC, 0, "CONNECT www.google.com:443 HTTP/1.1\r\n"
383 "Host: www.google.com\r\n"
384 "Proxy-Connection: keep-alive\r\n\r\n"),
386 MockRead reads[] = {
387 // No credentials.
388 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
389 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
390 MockRead(ASYNC, 3, "Content-Length: 10\r\n\r\n"),
391 MockRead(ASYNC, 4, "0123456789"),
393 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
394 NULL, 0, 1, LOW, HostPortPair("www.google.com", 443)));
395 scoped_ptr<SpdyFrame> rst(
396 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
397 MockWrite spdy_writes[] = {
398 CreateMockWrite(*req, 0, ASYNC),
399 CreateMockWrite(*rst, 2, ASYNC),
401 SpdyHeaderBlock resp_block;
402 resp_block[spdy_util_.GetStatusKey()] = "407";
403 resp_block["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
404 spdy_util_.MaybeAddVersionHeader(&resp_block);
406 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, resp_block));
407 MockRead spdy_reads[] = {
408 CreateMockRead(*resp, 1, ASYNC),
409 MockRead(ASYNC, 0, 3)
412 Initialize(reads, arraysize(reads), writes, arraysize(writes),
413 spdy_reads, arraysize(spdy_reads), spdy_writes,
414 arraysize(spdy_writes));
416 data_->StopAfter(4);
417 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
418 callback_.callback(), &pool_, BoundNetLog());
419 EXPECT_EQ(ERR_IO_PENDING, rv);
420 EXPECT_FALSE(handle_.is_initialized());
421 EXPECT_FALSE(handle_.socket());
423 data_->RunFor(GetParam().proxy_type == SPDY ? 2 : 4);
424 rv = callback_.WaitForResult();
425 EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, rv);
426 EXPECT_TRUE(handle_.is_initialized());
427 ASSERT_TRUE(handle_.socket());
428 ProxyClientSocket* tunnel_socket =
429 static_cast<ProxyClientSocket*>(handle_.socket());
430 if (GetParam().proxy_type == SPDY) {
431 EXPECT_TRUE(tunnel_socket->IsConnected());
432 EXPECT_TRUE(tunnel_socket->IsUsingSpdy());
433 } else {
434 EXPECT_FALSE(tunnel_socket->IsConnected());
435 EXPECT_FALSE(tunnel_socket->IsUsingSpdy());
439 TEST_P(HttpProxyClientSocketPoolTest, HaveAuth) {
440 // It's pretty much impossible to make the SPDY case behave synchronously
441 // so we skip this test for SPDY
442 if (GetParam().proxy_type == SPDY)
443 return;
444 std::string proxy_host_port =
445 GetParam().proxy_type == HTTP ?
446 (kHttpProxyHost + std::string(":80")) :
447 (kHttpsProxyHost + std::string(":443"));
448 std::string request =
449 "CONNECT www.google.com:443 HTTP/1.1\r\n"
450 "Host: www.google.com\r\n"
451 "Proxy-Connection: keep-alive\r\n"
452 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
453 "Foo: " + proxy_host_port + "\r\n\r\n";
454 MockWrite writes[] = {
455 MockWrite(SYNCHRONOUS, 0, request.c_str()),
457 MockRead reads[] = {
458 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
461 Initialize(reads, arraysize(reads), writes, arraysize(writes), NULL, 0,
462 NULL, 0);
463 AddAuthToCache();
465 scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
466 int rv = handle_.Init("a", CreateTunnelParams(proxy_delegate.get()), LOW,
467 callback_.callback(), &pool_, BoundNetLog());
468 EXPECT_EQ(OK, rv);
469 EXPECT_TRUE(handle_.is_initialized());
470 ASSERT_TRUE(handle_.socket());
471 HttpProxyClientSocket* tunnel_socket =
472 static_cast<HttpProxyClientSocket*>(handle_.socket());
473 EXPECT_TRUE(tunnel_socket->IsConnected());
474 proxy_delegate->VerifyOnTunnelHeadersReceived(
475 "www.google.com:443",
476 proxy_host_port.c_str(),
477 "HTTP/1.1 200 Connection Established");
478 proxy_delegate->VerifyOnTunnelRequestCompleted(
479 "www.google.com:443",
480 proxy_host_port.c_str());
483 TEST_P(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
484 std::string proxy_host_port =
485 GetParam().proxy_type == HTTP ?
486 (kHttpProxyHost + std::string(":80")) :
487 (kHttpsProxyHost + std::string(":443"));
488 std::string request =
489 "CONNECT www.google.com:443 HTTP/1.1\r\n"
490 "Host: www.google.com\r\n"
491 "Proxy-Connection: keep-alive\r\n"
492 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
493 "Foo: " + proxy_host_port + "\r\n\r\n";
494 MockWrite writes[] = {
495 MockWrite(ASYNC, 0, request.c_str()),
497 MockRead reads[] = {
498 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
501 scoped_ptr<SpdyFrame> req(
502 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
503 HostPortPair("www.google.com", 443)));
504 MockWrite spdy_writes[] = {
505 CreateMockWrite(*req, 0, ASYNC)
507 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
508 MockRead spdy_reads[] = {
509 CreateMockRead(*resp, 1, ASYNC),
510 MockRead(ASYNC, 0, 2)
513 Initialize(reads, arraysize(reads), writes, arraysize(writes),
514 spdy_reads, arraysize(spdy_reads), spdy_writes,
515 arraysize(spdy_writes));
516 AddAuthToCache();
518 scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
519 int rv = handle_.Init("a", CreateTunnelParams(proxy_delegate.get()), LOW,
520 callback_.callback(), &pool_, BoundNetLog());
521 EXPECT_EQ(ERR_IO_PENDING, rv);
522 EXPECT_FALSE(handle_.is_initialized());
523 EXPECT_FALSE(handle_.socket());
525 data_->RunFor(2);
526 EXPECT_EQ(OK, callback_.WaitForResult());
527 EXPECT_TRUE(handle_.is_initialized());
528 ASSERT_TRUE(handle_.socket());
529 HttpProxyClientSocket* tunnel_socket =
530 static_cast<HttpProxyClientSocket*>(handle_.socket());
531 EXPECT_TRUE(tunnel_socket->IsConnected());
532 proxy_delegate->VerifyOnTunnelRequestCompleted(
533 "www.google.com:443",
534 proxy_host_port.c_str());
537 // Make sure that HttpProxyConnectJob passes on its priority to its
538 // SPDY session's socket request on Init (if applicable).
539 TEST_P(HttpProxyClientSocketPoolTest,
540 SetSpdySessionSocketRequestPriorityOnInit) {
541 if (GetParam().proxy_type != SPDY)
542 return;
544 scoped_ptr<SpdyFrame> req(
545 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, MEDIUM,
546 HostPortPair("www.google.com", 443)));
547 MockWrite spdy_writes[] = {
548 CreateMockWrite(*req, 0, ASYNC)
550 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
551 MockRead spdy_reads[] = {
552 CreateMockRead(*resp, 1, ASYNC),
553 MockRead(ASYNC, 0, 2)
556 Initialize(NULL, 0, NULL, 0,
557 spdy_reads, arraysize(spdy_reads),
558 spdy_writes, arraysize(spdy_writes));
559 AddAuthToCache();
561 EXPECT_EQ(ERR_IO_PENDING,
562 handle_.Init("a", CreateTunnelParams(NULL), MEDIUM,
563 callback_.callback(), &pool_, BoundNetLog()));
564 EXPECT_EQ(MEDIUM, GetLastTransportRequestPriority());
566 data_->RunFor(2);
567 EXPECT_EQ(OK, callback_.WaitForResult());
570 TEST_P(HttpProxyClientSocketPoolTest, TCPError) {
571 if (GetParam().proxy_type == SPDY) return;
572 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
573 data_->set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_CLOSED));
575 socket_factory()->AddSocketDataProvider(data_.get());
577 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
578 callback_.callback(), &pool_, BoundNetLog());
579 EXPECT_EQ(ERR_IO_PENDING, rv);
580 EXPECT_FALSE(handle_.is_initialized());
581 EXPECT_FALSE(handle_.socket());
583 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, callback_.WaitForResult());
585 EXPECT_FALSE(handle_.is_initialized());
586 EXPECT_FALSE(handle_.socket());
589 TEST_P(HttpProxyClientSocketPoolTest, SSLError) {
590 if (GetParam().proxy_type == HTTP) return;
591 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
592 data_->set_connect_data(MockConnect(ASYNC, OK));
593 socket_factory()->AddSocketDataProvider(data_.get());
595 ssl_data_.reset(new SSLSocketDataProvider(ASYNC,
596 ERR_CERT_AUTHORITY_INVALID));
597 if (GetParam().proxy_type == SPDY) {
598 InitializeSpdySsl();
600 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
602 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
603 callback_.callback(), &pool_, BoundNetLog());
604 EXPECT_EQ(ERR_IO_PENDING, rv);
605 EXPECT_FALSE(handle_.is_initialized());
606 EXPECT_FALSE(handle_.socket());
608 EXPECT_EQ(ERR_PROXY_CERTIFICATE_INVALID, callback_.WaitForResult());
610 EXPECT_FALSE(handle_.is_initialized());
611 EXPECT_FALSE(handle_.socket());
614 TEST_P(HttpProxyClientSocketPoolTest, SslClientAuth) {
615 if (GetParam().proxy_type == HTTP) return;
616 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
617 data_->set_connect_data(MockConnect(ASYNC, OK));
618 socket_factory()->AddSocketDataProvider(data_.get());
620 ssl_data_.reset(new SSLSocketDataProvider(ASYNC,
621 ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
622 if (GetParam().proxy_type == SPDY) {
623 InitializeSpdySsl();
625 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
627 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
628 callback_.callback(), &pool_, BoundNetLog());
629 EXPECT_EQ(ERR_IO_PENDING, rv);
630 EXPECT_FALSE(handle_.is_initialized());
631 EXPECT_FALSE(handle_.socket());
633 EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, callback_.WaitForResult());
635 EXPECT_FALSE(handle_.is_initialized());
636 EXPECT_FALSE(handle_.socket());
639 TEST_P(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
640 MockWrite writes[] = {
641 MockWrite(ASYNC, 0,
642 "CONNECT www.google.com:443 HTTP/1.1\r\n"
643 "Host: www.google.com\r\n"
644 "Proxy-Connection: keep-alive\r\n"
645 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
647 MockRead reads[] = {
648 MockRead(ASYNC, 1, "HTTP/1.1 200 Conn"),
649 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 2),
651 scoped_ptr<SpdyFrame> req(
652 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
653 HostPortPair("www.google.com", 443)));
654 MockWrite spdy_writes[] = {
655 CreateMockWrite(*req, 0, ASYNC)
657 MockRead spdy_reads[] = {
658 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 1),
661 Initialize(reads, arraysize(reads), writes, arraysize(writes),
662 spdy_reads, arraysize(spdy_reads), spdy_writes,
663 arraysize(spdy_writes));
664 AddAuthToCache();
666 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
667 callback_.callback(), &pool_, BoundNetLog());
668 EXPECT_EQ(ERR_IO_PENDING, rv);
669 EXPECT_FALSE(handle_.is_initialized());
670 EXPECT_FALSE(handle_.socket());
672 data_->RunFor(3);
673 if (GetParam().proxy_type == SPDY) {
674 // SPDY cannot process a headers block unless it's complete and so it
675 // returns ERR_CONNECTION_CLOSED in this case.
676 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback_.WaitForResult());
677 } else {
678 EXPECT_EQ(ERR_RESPONSE_HEADERS_TRUNCATED, callback_.WaitForResult());
680 EXPECT_FALSE(handle_.is_initialized());
681 EXPECT_FALSE(handle_.socket());
684 TEST_P(HttpProxyClientSocketPoolTest, Tunnel1xxResponse) {
685 // Tests that 1xx responses are rejected for a CONNECT request.
686 if (GetParam().proxy_type == SPDY) {
687 // SPDY doesn't have 1xx responses.
688 return;
691 MockWrite writes[] = {
692 MockWrite(ASYNC, 0,
693 "CONNECT www.google.com:443 HTTP/1.1\r\n"
694 "Host: www.google.com\r\n"
695 "Proxy-Connection: keep-alive\r\n\r\n"),
697 MockRead reads[] = {
698 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
699 MockRead(ASYNC, 2, "HTTP/1.1 200 Connection Established\r\n\r\n"),
702 Initialize(reads, arraysize(reads), writes, arraysize(writes),
703 NULL, 0, NULL, 0);
705 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
706 callback_.callback(), &pool_, BoundNetLog());
707 EXPECT_EQ(ERR_IO_PENDING, rv);
708 EXPECT_FALSE(handle_.is_initialized());
709 EXPECT_FALSE(handle_.socket());
711 data_->RunFor(2);
712 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult());
715 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupError) {
716 MockWrite writes[] = {
717 MockWrite(ASYNC, 0,
718 "CONNECT www.google.com:443 HTTP/1.1\r\n"
719 "Host: www.google.com\r\n"
720 "Proxy-Connection: keep-alive\r\n"
721 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
723 MockRead reads[] = {
724 MockRead(ASYNC, 1, "HTTP/1.1 304 Not Modified\r\n\r\n"),
726 scoped_ptr<SpdyFrame> req(
727 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
728 HostPortPair("www.google.com", 443)));
729 scoped_ptr<SpdyFrame> rst(
730 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
731 MockWrite spdy_writes[] = {
732 CreateMockWrite(*req, 0, ASYNC),
733 CreateMockWrite(*rst, 2, ASYNC),
735 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
736 MockRead spdy_reads[] = {
737 CreateMockRead(*resp, 1, ASYNC),
738 MockRead(ASYNC, 0, 3),
741 Initialize(reads, arraysize(reads), writes, arraysize(writes),
742 spdy_reads, arraysize(spdy_reads), spdy_writes,
743 arraysize(spdy_writes));
744 AddAuthToCache();
746 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
747 callback_.callback(), &pool_, BoundNetLog());
748 EXPECT_EQ(ERR_IO_PENDING, rv);
749 EXPECT_FALSE(handle_.is_initialized());
750 EXPECT_FALSE(handle_.socket());
752 data_->RunFor(2);
754 rv = callback_.WaitForResult();
755 // All Proxy CONNECT responses are not trustworthy
756 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
757 EXPECT_FALSE(handle_.is_initialized());
758 EXPECT_FALSE(handle_.socket());
761 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupRedirect) {
762 const std::string redirectTarget = "https://foo.google.com/";
764 const std::string responseText = "HTTP/1.1 302 Found\r\n"
765 "Location: " + redirectTarget + "\r\n"
766 "Set-Cookie: foo=bar\r\n"
767 "\r\n";
768 MockWrite writes[] = {
769 MockWrite(ASYNC, 0,
770 "CONNECT www.google.com:443 HTTP/1.1\r\n"
771 "Host: www.google.com\r\n"
772 "Proxy-Connection: keep-alive\r\n"
773 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
775 MockRead reads[] = {
776 MockRead(ASYNC, 1, responseText.c_str()),
778 scoped_ptr<SpdyFrame> req(
779 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
780 HostPortPair("www.google.com", 443)));
781 scoped_ptr<SpdyFrame> rst(
782 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
784 MockWrite spdy_writes[] = {
785 CreateMockWrite(*req, 0, ASYNC),
786 CreateMockWrite(*rst, 3, ASYNC),
789 const char* const responseHeaders[] = {
790 "location", redirectTarget.c_str(),
791 "set-cookie", "foo=bar",
793 const int responseHeadersSize = arraysize(responseHeaders) / 2;
794 scoped_ptr<SpdyFrame> resp(
795 spdy_util_.ConstructSpdySynReplyError(
796 "302 Found",
797 responseHeaders, responseHeadersSize,
798 1));
799 MockRead spdy_reads[] = {
800 CreateMockRead(*resp, 1, ASYNC),
801 MockRead(ASYNC, 0, 2),
804 Initialize(reads, arraysize(reads), writes, arraysize(writes),
805 spdy_reads, arraysize(spdy_reads), spdy_writes,
806 arraysize(spdy_writes));
807 AddAuthToCache();
809 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
810 callback_.callback(), &pool_, BoundNetLog());
811 EXPECT_EQ(ERR_IO_PENDING, rv);
812 EXPECT_FALSE(handle_.is_initialized());
813 EXPECT_FALSE(handle_.socket());
815 data_->RunFor(2);
817 rv = callback_.WaitForResult();
819 if (GetParam().proxy_type == HTTP) {
820 // We don't trust 302 responses to CONNECT from HTTP proxies.
821 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
822 EXPECT_FALSE(handle_.is_initialized());
823 EXPECT_FALSE(handle_.socket());
824 } else {
825 // Expect ProxyClientSocket to return the proxy's response, sanitized.
826 EXPECT_EQ(ERR_HTTPS_PROXY_TUNNEL_RESPONSE, rv);
827 EXPECT_TRUE(handle_.is_initialized());
828 ASSERT_TRUE(handle_.socket());
830 const ProxyClientSocket* tunnel_socket =
831 static_cast<ProxyClientSocket*>(handle_.socket());
832 const HttpResponseInfo* response = tunnel_socket->GetConnectResponseInfo();
833 const HttpResponseHeaders* headers = response->headers.get();
835 // Make sure Set-Cookie header was stripped.
836 EXPECT_FALSE(headers->HasHeader("set-cookie"));
838 // Make sure Content-Length: 0 header was added.
839 EXPECT_TRUE(headers->HasHeaderValue("content-length", "0"));
841 // Make sure Location header was included and correct.
842 std::string location;
843 EXPECT_TRUE(headers->IsRedirect(&location));
844 EXPECT_EQ(location, redirectTarget);
848 // It would be nice to also test the timeouts in HttpProxyClientSocketPool.
850 } // namespace
852 } // namespace net