blob: ac86082807eae8ddd8849ec25a4b57a782588ff2 [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]95d88ffe2010-02-04 21:25:338#include <vector>
[email protected]77848d12008-11-14 00:00:229
[email protected]2d731a32010-04-29 01:04:0610#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3011#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3312#include "base/file_path.h"
13#include "base/file_util.h"
[email protected]3b63f8f42011-03-28 01:54:1514#include "base/memory/scoped_ptr.h"
[email protected]5e6efa52011-06-27 17:26:4115#include "base/metrics/histogram.h"
[email protected]be1ce6a72010-08-03 14:35:2216#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3517#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1218#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3319#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3220#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1221#include "net/base/net_log.h"
22#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3123#include "net/base/request_priority.h"
[email protected]bd0b6772011-01-11 19:59:3024#include "net/base/ssl_cert_request_info.h"
[email protected]db36938c2009-08-19 21:48:4225#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3326#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5227#include "net/base/test_completion_callback.h"
28#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1229#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0030#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2931#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5732#include "net/http/http_basic_stream.h"
[email protected]3deb9a52010-11-11 00:24:4033#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5234#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5635#include "net/http/http_network_session_peer.h"
[email protected]0877e3d2009-10-17 22:29:5736#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3837#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5238#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5339#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1140#include "net/proxy/proxy_resolver.h"
41#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4442#include "net/socket/client_socket_factory.h"
43#include "net/socket/socket_test_util.h"
44#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5445#include "net/spdy/spdy_framer.h"
46#include "net/spdy/spdy_session.h"
47#include "net/spdy/spdy_session_pool.h"
48#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5249#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1550#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5251
52//-----------------------------------------------------------------------------
53
[email protected]13c8a092010-07-29 06:15:4454namespace {
55
56const string16 kBar(ASCIIToUTF16("bar"));
57const string16 kBar2(ASCIIToUTF16("bar2"));
58const string16 kBar3(ASCIIToUTF16("bar3"));
59const string16 kBaz(ASCIIToUTF16("baz"));
60const string16 kFirst(ASCIIToUTF16("first"));
61const string16 kFoo(ASCIIToUTF16("foo"));
62const string16 kFoo2(ASCIIToUTF16("foo2"));
63const string16 kFoo3(ASCIIToUTF16("foo3"));
64const string16 kFou(ASCIIToUTF16("fou"));
65const string16 kSecond(ASCIIToUTF16("second"));
66const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
67const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
68
69} // namespace
70
[email protected]89ceba9a2009-03-21 03:46:0671namespace net {
72
[email protected]e44de5d2009-06-05 20:12:4573// Helper to manage the lifetimes of the dependencies for a
74// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4475struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5976 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4277 SessionDependencies()
78 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:1579 cert_verifier(new CertVerifier),
[email protected]ebeefff32010-09-15 05:10:0280 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:1081 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0882 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5483 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5484 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5985
86 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4587 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4288 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:1589 cert_verifier(new CertVerifier),
[email protected]db36938c2009-08-19 21:48:4290 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1091 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0892 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5493 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5494 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5995
[email protected]73c45322010-10-01 23:57:5496 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]822581d2010-12-16 17:27:1597 scoped_ptr<CertVerifier> cert_verifier;
[email protected]6104ea5d2011-04-27 21:37:1298 scoped_ptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4299 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59100 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50101 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a7ea8832010-07-12 17:54:54102 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59103};
104
[email protected]228ff742009-06-05 01:19:59105HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]9e1bdd32011-02-03 21:48:34106 net::HttpNetworkSession::Params params;
107 params.client_socket_factory = &session_deps->socket_factory;
108 params.host_resolver = session_deps->host_resolver.get();
109 params.cert_verifier = session_deps->cert_verifier.get();
[email protected]6104ea5d2011-04-27 21:37:12110 params.proxy_service = session_deps->proxy_service.get();
[email protected]9e1bdd32011-02-03 21:48:34111 params.ssl_config_service = session_deps->ssl_config_service;
112 params.http_auth_handler_factory =
113 session_deps->http_auth_handler_factory.get();
114 params.net_log = session_deps->net_log;
115 return new HttpNetworkSession(params);
[email protected]e8d536192008-10-17 22:21:14116}
117
[email protected]89836e22008-09-25 20:33:42118class HttpNetworkTransactionTest : public PlatformTest {
[email protected]e3ceb682011-06-28 23:55:46119 protected:
120 struct SimpleGetHelperResult {
121 int rv;
122 std::string status_line;
123 std::string response_data;
124 };
125
[email protected]2ff8b312010-04-26 22:20:54126 virtual void SetUp() {
[email protected]e3ceb682011-06-28 23:55:46127 disabled_spdy_session_domain_verification_ = false;
[email protected]0b0bf032010-09-21 18:08:50128 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
129 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54130 spdy::SpdyFramer::set_enable_compression_default(false);
131 }
132
[email protected]0e75a732008-10-16 20:36:09133 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50134 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
135 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54136 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09137 // Empty the current queue.
138 MessageLoop::current()->RunAllPending();
139 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50140 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
141 MessageLoop::current()->RunAllPending();
[email protected]e3ceb682011-06-28 23:55:46142 if (disabled_spdy_session_domain_verification_) {
143 SpdySession::SetDomainVerification(
144 spdy_session_domain_verification_old_value_);
145 }
[email protected]0e75a732008-10-16 20:36:09146 }
147
[email protected]3d2a59b2008-09-26 19:44:25148 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52149
[email protected]31a2bfe2010-02-09 08:03:39150 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
151 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15152 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52153
[email protected]ff007e162009-05-23 09:13:15154 HttpRequestInfo request;
155 request.method = "GET";
156 request.url = GURL("http://www.google.com/");
157 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52158
[email protected]cb9bf6ca2011-01-28 13:15:27159 SessionDependencies session_deps;
160 scoped_ptr<HttpTransaction> trans(
161 new HttpNetworkTransaction(CreateSession(&session_deps)));
162
[email protected]31a2bfe2010-02-09 08:03:39163 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59164 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52165
[email protected]ff007e162009-05-23 09:13:15166 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52167
[email protected]169d0012010-05-10 23:20:12168 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]3deb9a52010-11-11 00:24:40169 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
[email protected]169d0012010-05-10 23:20:12170 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15171 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52172
[email protected]ff007e162009-05-23 09:13:15173 out.rv = callback.WaitForResult();
174 if (out.rv != OK)
175 return out;
176
177 const HttpResponseInfo* response = trans->GetResponseInfo();
178 EXPECT_TRUE(response != NULL);
179
180 EXPECT_TRUE(response->headers != NULL);
181 out.status_line = response->headers->GetStatusLine();
182
[email protected]6d81b482011-02-22 19:47:19183 EXPECT_EQ("192.0.2.33", response->socket_address.host());
184 EXPECT_EQ(0, response->socket_address.port());
185
[email protected]ff007e162009-05-23 09:13:15186 rv = ReadTransaction(trans.get(), &out.response_data);
187 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40188
189 net::CapturingNetLog::EntryList entries;
190 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39191 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40192 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12193 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39194 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40195 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39196 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
197 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15198
[email protected]b2fcd0e2010-12-01 15:19:40199 CapturingNetLog::Entry entry = entries[pos];
[email protected]3deb9a52010-11-11 00:24:40200 NetLogHttpRequestParameter* request_params =
201 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
202 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
203 EXPECT_EQ("Host: www.google.com\r\n"
204 "Connection: keep-alive\r\n\r\n",
205 request_params->GetHeaders().ToString());
206
[email protected]aecfbf22008-10-16 02:02:47207 return out;
[email protected]ff007e162009-05-23 09:13:15208 }
initial.commit586acc5fe2008-07-26 22:42:52209
[email protected]ff007e162009-05-23 09:13:15210 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
211 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52212
[email protected]ff007e162009-05-23 09:13:15213 void ConnectStatusHelper(const MockRead& status);
[email protected]e3ceb682011-06-28 23:55:46214
215 void DisableSpdySessionDomainVerification() {
216 disabled_spdy_session_domain_verification_ = true;
217 spdy_session_domain_verification_old_value_ =
218 SpdySession::SetDomainVerification(false);
219 }
220
221 bool disabled_spdy_session_domain_verification_;
222 bool spdy_session_domain_verification_old_value_;
[email protected]ff007e162009-05-23 09:13:15223};
[email protected]231d5a32008-09-13 00:45:27224
[email protected]15a5ccf82008-10-23 19:57:43225// Fill |str| with a long header list that consumes >= |size| bytes.
226void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19227 const char* row =
228 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
229 const int sizeof_row = strlen(row);
230 const int num_rows = static_cast<int>(
231 ceil(static_cast<float>(size) / sizeof_row));
232 const int sizeof_data = num_rows * sizeof_row;
233 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43234 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51235
[email protected]4ddaf2502008-10-23 18:26:19236 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43237 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19238}
239
[email protected]385a4672009-03-11 22:21:29240// Alternative functions that eliminate randomness and dependency on the local
241// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20242void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29243 static const uint8 bytes[] = {
244 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
245 };
246 static size_t current_byte = 0;
247 for (size_t i = 0; i < n; ++i) {
248 output[i] = bytes[current_byte++];
249 current_byte %= arraysize(bytes);
250 }
251}
252
[email protected]fe2bc6a2009-03-23 16:52:20253void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29254 static const uint8 bytes[] = {
255 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
256 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
257 };
258 static size_t current_byte = 0;
259 for (size_t i = 0; i < n; ++i) {
260 output[i] = bytes[current_byte++];
261 current_byte %= arraysize(bytes);
262 }
263}
264
[email protected]fe2bc6a2009-03-23 16:52:20265std::string MockGetHostName() {
266 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29267}
268
[email protected]e60e47a2010-07-14 03:37:18269template<typename ParentPool>
270class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31271 public:
[email protected]9e1bdd32011-02-03 21:48:34272 CaptureGroupNameSocketPool(HostResolver* host_resolver,
273 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18274
[email protected]d80a4322009-08-14 07:07:49275 const std::string last_group_name_received() const {
276 return last_group_name_;
277 }
278
[email protected]684970b2009-08-14 04:54:46279 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49280 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31281 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31282 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46283 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53284 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31285 last_group_name_ = group_name;
286 return ERR_IO_PENDING;
287 }
[email protected]04e5be32009-06-26 20:00:31288 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21289 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31290 virtual void ReleaseSocket(const std::string& group_name,
[email protected]3268023f2011-05-05 00:08:10291 StreamSocket* socket,
[email protected]9f95c692011-02-11 19:20:19292 int id) {}
[email protected]04e5be32009-06-26 20:00:31293 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31294 virtual int IdleSocketCount() const {
295 return 0;
296 }
297 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
298 return 0;
299 }
300 virtual LoadState GetLoadState(const std::string& group_name,
301 const ClientSocketHandle* handle) const {
302 return LOAD_STATE_IDLE;
303 }
[email protected]a796bcec2010-03-22 17:17:26304 virtual base::TimeDelta ConnectionTimeout() const {
305 return base::TimeDelta();
306 }
[email protected]d80a4322009-08-14 07:07:49307
308 private:
[email protected]04e5be32009-06-26 20:00:31309 std::string last_group_name_;
310};
311
[email protected]ab739042011-04-07 15:22:28312typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
313CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13314typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
315CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06316typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11317CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18318typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
319CaptureGroupNameSSLSocketPool;
320
321template<typename ParentPool>
322CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34323 HostResolver* host_resolver,
324 CertVerifier* /* cert_verifier */)
325 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
[email protected]e60e47a2010-07-14 03:37:18326
327template<>
[email protected]2df19bb2010-08-25 20:13:46328CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34329 HostResolver* host_resolver,
330 CertVerifier* /* cert_verifier */)
331 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
[email protected]2df19bb2010-08-25 20:13:46332
333template<>
[email protected]e60e47a2010-07-14 03:37:18334CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34335 HostResolver* host_resolver,
336 CertVerifier* cert_verifier)
337 : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL, NULL,
[email protected]345c613b2010-11-22 19:33:18338 NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11339
[email protected]231d5a32008-09-13 00:45:27340//-----------------------------------------------------------------------------
341
[email protected]dae22c52010-07-30 02:16:35342// This is the expected list of advertised protocols from the browser's NPN
343// list.
344static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
345
346// This is the expected return from a current server advertising SPDY.
347static const char kAlternateProtocolHttpHeader[] =
348 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
349
[email protected]5e6efa52011-06-27 17:26:41350TEST_F(HttpNetworkTransactionTest, LogNumRttVsBytesMetrics_WarmestSocket) {
351 MockRead data_reads[1000];
352 data_reads[0] = MockRead("HTTP/1.0 200 OK\r\n\r\n");
353 for (int i = 1; i < 999; i++) {
354 data_reads[i] = MockRead("Gagan is a good boy!");
355 }
356 data_reads[999] = MockRead(false, OK);
357
358 net::SetSocketReusePolicy(0);
359 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
360 arraysize(data_reads));
361
362 base::Histogram* histogram = NULL;
363 base::StatisticsRecorder::FindHistogram(
364 "Net.Num_RTT_vs_KB_warmest_socket_15KB", &histogram);
365 CHECK(histogram);
366
367 base::Histogram::SampleSet sample_set;
368 histogram->SnapshotSample(&sample_set);
369 EXPECT_EQ(1, sample_set.TotalCount());
370
371 EXPECT_EQ(OK, out.rv);
372 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
373}
374
375// TODO(gagansingh): Add test for LogNumRttVsBytesMetrics_LastAccessSocket once
376// it is possible to clear histograms from previous tests.
377
[email protected]231d5a32008-09-13 00:45:27378TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59379 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40380 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43381 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27382}
383
384TEST_F(HttpNetworkTransactionTest, SimpleGET) {
385 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35386 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
387 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42388 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27389 };
[email protected]31a2bfe2010-02-09 08:03:39390 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
391 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42392 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27393 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
394 EXPECT_EQ("hello world", out.response_data);
395}
396
397// Response with no status line.
398TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
399 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35400 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42401 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27402 };
[email protected]31a2bfe2010-02-09 08:03:39403 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
404 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42405 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27406 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
407 EXPECT_EQ("hello world", out.response_data);
408}
409
410// Allow up to 4 bytes of junk to precede status line.
411TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
412 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35413 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42414 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27415 };
[email protected]31a2bfe2010-02-09 08:03:39416 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
417 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42418 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27419 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
420 EXPECT_EQ("DATA", out.response_data);
421}
422
423// Allow up to 4 bytes of junk to precede status line.
424TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
425 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35426 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42427 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27428 };
[email protected]31a2bfe2010-02-09 08:03:39429 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
430 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42431 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27432 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
433 EXPECT_EQ("DATA", out.response_data);
434}
435
436// Beyond 4 bytes of slop and it should fail to find a status line.
437TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
438 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35439 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42440 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27441 };
[email protected]31a2bfe2010-02-09 08:03:39442 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
443 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42444 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25445 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
446 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27447}
448
449// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
450TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
451 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35452 MockRead("\n"),
453 MockRead("\n"),
454 MockRead("Q"),
455 MockRead("J"),
456 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42457 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27458 };
[email protected]31a2bfe2010-02-09 08:03:39459 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
460 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42461 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27462 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
463 EXPECT_EQ("DATA", out.response_data);
464}
465
466// Close the connection before enough bytes to have a status line.
467TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
468 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35469 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42470 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27471 };
[email protected]31a2bfe2010-02-09 08:03:39472 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
473 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42474 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27475 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
476 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52477}
478
[email protected]f9d44aa2008-09-23 23:57:17479// Simulate a 204 response, lacking a Content-Length header, sent over a
480// persistent connection. The response should still terminate since a 204
481// cannot have a response body.
482TEST_F(HttpNetworkTransactionTest, StopsReading204) {
483 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35484 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
485 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42486 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17487 };
[email protected]31a2bfe2010-02-09 08:03:39488 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
489 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42490 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17491 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
492 EXPECT_EQ("", out.response_data);
493}
494
[email protected]0877e3d2009-10-17 22:29:57495// A simple request using chunked encoding with some extra data after.
496// (Like might be seen in a pipelined response.)
497TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
498 MockRead data_reads[] = {
499 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
500 MockRead("5\r\nHello\r\n"),
501 MockRead("1\r\n"),
502 MockRead(" \r\n"),
503 MockRead("5\r\nworld\r\n"),
504 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
505 MockRead(false, OK),
506 };
[email protected]31a2bfe2010-02-09 08:03:39507 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
508 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57509 EXPECT_EQ(OK, out.rv);
510 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
511 EXPECT_EQ("Hello world", out.response_data);
512}
513
[email protected]9fe44f52010-09-23 18:36:00514// Next tests deal with http://crbug.com/56344.
515
516TEST_F(HttpNetworkTransactionTest,
517 MultipleContentLengthHeadersNoTransferEncoding) {
518 MockRead data_reads[] = {
519 MockRead("HTTP/1.1 200 OK\r\n"),
520 MockRead("Content-Length: 10\r\n"),
521 MockRead("Content-Length: 5\r\n\r\n"),
522 };
523 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
524 arraysize(data_reads));
525 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
526}
527
528TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04529 DuplicateContentLengthHeadersNoTransferEncoding) {
530 MockRead data_reads[] = {
531 MockRead("HTTP/1.1 200 OK\r\n"),
532 MockRead("Content-Length: 5\r\n"),
533 MockRead("Content-Length: 5\r\n\r\n"),
534 MockRead("Hello"),
535 };
536 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
537 arraysize(data_reads));
538 EXPECT_EQ(OK, out.rv);
539 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
540 EXPECT_EQ("Hello", out.response_data);
541}
542
543TEST_F(HttpNetworkTransactionTest,
544 ComplexContentLengthHeadersNoTransferEncoding) {
545 // More than 2 dupes.
546 {
547 MockRead data_reads[] = {
548 MockRead("HTTP/1.1 200 OK\r\n"),
549 MockRead("Content-Length: 5\r\n"),
550 MockRead("Content-Length: 5\r\n"),
551 MockRead("Content-Length: 5\r\n\r\n"),
552 MockRead("Hello"),
553 };
554 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
555 arraysize(data_reads));
556 EXPECT_EQ(OK, out.rv);
557 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
558 EXPECT_EQ("Hello", out.response_data);
559 }
560 // HTTP/1.0
561 {
562 MockRead data_reads[] = {
563 MockRead("HTTP/1.0 200 OK\r\n"),
564 MockRead("Content-Length: 5\r\n"),
565 MockRead("Content-Length: 5\r\n"),
566 MockRead("Content-Length: 5\r\n\r\n"),
567 MockRead("Hello"),
568 };
569 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
570 arraysize(data_reads));
571 EXPECT_EQ(OK, out.rv);
572 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
573 EXPECT_EQ("Hello", out.response_data);
574 }
575 // 2 dupes and one mismatched.
576 {
577 MockRead data_reads[] = {
578 MockRead("HTTP/1.1 200 OK\r\n"),
579 MockRead("Content-Length: 10\r\n"),
580 MockRead("Content-Length: 10\r\n"),
581 MockRead("Content-Length: 5\r\n\r\n"),
582 };
583 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
584 arraysize(data_reads));
585 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
586 }
587}
588
589TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00590 MultipleContentLengthHeadersTransferEncoding) {
591 MockRead data_reads[] = {
592 MockRead("HTTP/1.1 200 OK\r\n"),
593 MockRead("Content-Length: 666\r\n"),
594 MockRead("Content-Length: 1337\r\n"),
595 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
596 MockRead("5\r\nHello\r\n"),
597 MockRead("1\r\n"),
598 MockRead(" \r\n"),
599 MockRead("5\r\nworld\r\n"),
600 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
601 MockRead(false, OK),
602 };
603 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
604 arraysize(data_reads));
605 EXPECT_EQ(OK, out.rv);
606 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
607 EXPECT_EQ("Hello world", out.response_data);
608}
609
[email protected]ef0faf2e72009-03-05 23:27:23610// Do a request using the HEAD method. Verify that we don't try to read the
611// message body (since HEAD has none).
612TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:42613 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23614 request.method = "HEAD";
615 request.url = GURL("http://www.google.com/");
616 request.load_flags = 0;
617
[email protected]cb9bf6ca2011-01-28 13:15:27618 SessionDependencies session_deps;
619 scoped_ptr<HttpTransaction> trans(
620 new HttpNetworkTransaction(CreateSession(&session_deps)));
621
[email protected]ef0faf2e72009-03-05 23:27:23622 MockWrite data_writes1[] = {
623 MockWrite("HEAD / HTTP/1.1\r\n"
624 "Host: www.google.com\r\n"
625 "Connection: keep-alive\r\n"
626 "Content-Length: 0\r\n\r\n"),
627 };
628 MockRead data_reads1[] = {
629 MockRead("HTTP/1.1 404 Not Found\r\n"),
630 MockRead("Server: Blah\r\n"),
631 MockRead("Content-Length: 1234\r\n\r\n"),
632
633 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42634 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23635 };
636
[email protected]31a2bfe2010-02-09 08:03:39637 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
638 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59639 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23640
641 TestCompletionCallback callback1;
642
[email protected]5a1d7ca2010-04-28 20:12:27643 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42644 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23645
646 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42647 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23648
[email protected]1c773ea12009-04-28 19:58:42649 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23650 EXPECT_FALSE(response == NULL);
651
652 // Check that the headers got parsed.
653 EXPECT_TRUE(response->headers != NULL);
654 EXPECT_EQ(1234, response->headers->GetContentLength());
655 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
656
657 std::string server_header;
658 void* iter = NULL;
659 bool has_server_header = response->headers->EnumerateHeader(
660 &iter, "Server", &server_header);
661 EXPECT_TRUE(has_server_header);
662 EXPECT_EQ("Blah", server_header);
663
664 // Reading should give EOF right away, since there is no message body
665 // (despite non-zero content-length).
666 std::string response_data;
667 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42668 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23669 EXPECT_EQ("", response_data);
670}
671
initial.commit586acc5fe2008-07-26 22:42:52672TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59673 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27674 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52675
676 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35677 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
678 MockRead("hello"),
679 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
680 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42681 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52682 };
[email protected]31a2bfe2010-02-09 08:03:39683 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59684 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52685
[email protected]0b0bf032010-09-21 18:08:50686 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52687 "hello", "world"
688 };
689
690 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42691 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52692 request.method = "GET";
693 request.url = GURL("http://www.google.com/");
694 request.load_flags = 0;
695
[email protected]cb9bf6ca2011-01-28 13:15:27696 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
697
initial.commit586acc5fe2008-07-26 22:42:52698 TestCompletionCallback callback;
699
[email protected]5a1d7ca2010-04-28 20:12:27700 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42701 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52702
703 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42704 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52705
[email protected]1c773ea12009-04-28 19:58:42706 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52707 EXPECT_TRUE(response != NULL);
708
709 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25710 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52711
712 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57713 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42714 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25715 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52716 }
717}
718
719TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]1c773ea12009-04-28 19:58:42720 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52721 request.method = "POST";
722 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42723 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52724 request.upload_data->AppendBytes("foo", 3);
725 request.load_flags = 0;
726
[email protected]cb9bf6ca2011-01-28 13:15:27727 SessionDependencies session_deps;
728 scoped_ptr<HttpTransaction> trans(
729 new HttpNetworkTransaction(CreateSession(&session_deps)));
730
initial.commit586acc5fe2008-07-26 22:42:52731 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35732 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
733 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
734 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42735 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52736 };
[email protected]31a2bfe2010-02-09 08:03:39737 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59738 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52739
740 TestCompletionCallback callback;
741
[email protected]5a1d7ca2010-04-28 20:12:27742 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42743 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52744
745 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42746 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52747
[email protected]1c773ea12009-04-28 19:58:42748 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52749 EXPECT_TRUE(response != NULL);
750
751 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25752 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52753
754 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57755 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42756 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25757 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52758}
759
[email protected]3a2d3662009-03-27 03:49:14760// This test is almost the same as Ignores100 above, but the response contains
761// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57762// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14763TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:42764 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14765 request.method = "GET";
766 request.url = GURL("http://www.foo.com/");
767 request.load_flags = 0;
768
[email protected]cb9bf6ca2011-01-28 13:15:27769 SessionDependencies session_deps;
770 scoped_ptr<HttpTransaction> trans(
771 new HttpNetworkTransaction(CreateSession(&session_deps)));
772
[email protected]3a2d3662009-03-27 03:49:14773 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57774 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
775 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14776 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42777 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14778 };
[email protected]31a2bfe2010-02-09 08:03:39779 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59780 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14781
782 TestCompletionCallback callback;
783
[email protected]5a1d7ca2010-04-28 20:12:27784 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42785 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14786
787 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42788 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14789
[email protected]1c773ea12009-04-28 19:58:42790 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14791 EXPECT_TRUE(response != NULL);
792
793 EXPECT_TRUE(response->headers != NULL);
794 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
795
796 std::string response_data;
797 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42798 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14799 EXPECT_EQ("hello world", response_data);
800}
801
[email protected]ee9410e72010-01-07 01:42:38802TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
[email protected]ee9410e72010-01-07 01:42:38803 HttpRequestInfo request;
804 request.method = "POST";
805 request.url = GURL("http://www.foo.com/");
806 request.load_flags = 0;
807
[email protected]cb9bf6ca2011-01-28 13:15:27808 SessionDependencies session_deps;
809 scoped_ptr<HttpTransaction> trans(
810 new HttpNetworkTransaction(CreateSession(&session_deps)));
811
[email protected]ee9410e72010-01-07 01:42:38812 MockRead data_reads[] = {
813 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
814 MockRead(true, 0),
815 };
[email protected]31a2bfe2010-02-09 08:03:39816 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38817 session_deps.socket_factory.AddSocketDataProvider(&data);
818
819 TestCompletionCallback callback;
820
[email protected]5a1d7ca2010-04-28 20:12:27821 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38822 EXPECT_EQ(ERR_IO_PENDING, rv);
823
824 rv = callback.WaitForResult();
825 EXPECT_EQ(OK, rv);
826
827 std::string response_data;
828 rv = ReadTransaction(trans.get(), &response_data);
829 EXPECT_EQ(OK, rv);
830 EXPECT_EQ("", response_data);
831}
832
833TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:38834 HttpRequestInfo request;
835 request.method = "POST";
836 request.url = GURL("http://www.foo.com/");
837 request.load_flags = 0;
838
[email protected]cb9bf6ca2011-01-28 13:15:27839 SessionDependencies session_deps;
840 scoped_ptr<HttpTransaction> trans(
841 new HttpNetworkTransaction(CreateSession(&session_deps)));
842
[email protected]ee9410e72010-01-07 01:42:38843 MockRead data_reads[] = {
844 MockRead(true, 0),
845 };
[email protected]31a2bfe2010-02-09 08:03:39846 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38847 session_deps.socket_factory.AddSocketDataProvider(&data);
848
849 TestCompletionCallback callback;
850
[email protected]5a1d7ca2010-04-28 20:12:27851 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38852 EXPECT_EQ(ERR_IO_PENDING, rv);
853
854 rv = callback.WaitForResult();
855 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
856}
857
[email protected]3d2a59b2008-09-26 19:44:25858// read_failure specifies a read failure that should cause the network
859// transaction to resend the request.
860void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
861 const MockRead& read_failure) {
[email protected]1c773ea12009-04-28 19:58:42862 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52863 request.method = "GET";
864 request.url = GURL("http://www.foo.com/");
865 request.load_flags = 0;
866
[email protected]cb9bf6ca2011-01-28 13:15:27867 SessionDependencies session_deps;
868 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
869
initial.commit586acc5fe2008-07-26 22:42:52870 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35871 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
872 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25873 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52874 };
[email protected]31a2bfe2010-02-09 08:03:39875 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59876 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52877
878 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35879 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
880 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42881 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52882 };
[email protected]31a2bfe2010-02-09 08:03:39883 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59884 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52885
886 const char* kExpectedResponseData[] = {
887 "hello", "world"
888 };
889
890 for (int i = 0; i < 2; ++i) {
891 TestCompletionCallback callback;
892
[email protected]5695b8c2009-09-30 21:36:43893 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52894
[email protected]5a1d7ca2010-04-28 20:12:27895 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42896 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52897
898 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42899 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52900
[email protected]1c773ea12009-04-28 19:58:42901 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52902 EXPECT_TRUE(response != NULL);
903
904 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25905 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52906
907 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57908 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42909 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25910 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52911 }
912}
[email protected]3d2a59b2008-09-26 19:44:25913
914TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42915 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25916 KeepAliveConnectionResendRequestTest(read_failure);
917}
918
919TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42920 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25921 KeepAliveConnectionResendRequestTest(read_failure);
922}
923
924TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42925 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25926 request.method = "GET";
927 request.url = GURL("http://www.google.com/");
928 request.load_flags = 0;
929
[email protected]cb9bf6ca2011-01-28 13:15:27930 SessionDependencies session_deps;
931 scoped_ptr<HttpTransaction> trans(
932 new HttpNetworkTransaction(CreateSession(&session_deps)));
933
[email protected]3d2a59b2008-09-26 19:44:25934 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42935 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35936 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
937 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42938 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25939 };
[email protected]31a2bfe2010-02-09 08:03:39940 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59941 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25942
943 TestCompletionCallback callback;
944
[email protected]5a1d7ca2010-04-28 20:12:27945 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42946 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25947
948 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42949 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25950
[email protected]1c773ea12009-04-28 19:58:42951 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25952 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25953}
954
955// What do various browsers do when the server closes a non-keepalive
956// connection without sending any response header or body?
957//
958// IE7: error page
959// Safari 3.1.2 (Windows): error page
960// Firefox 3.0.1: blank page
961// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42962// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
963// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25964TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
965 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42966 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35967 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
968 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42969 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25970 };
[email protected]31a2bfe2010-02-09 08:03:39971 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
972 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42973 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25974}
[email protected]038e9a32008-10-08 22:40:16975
[email protected]0b0bf032010-09-21 18:08:50976// Test that we correctly reuse a keep-alive connection after not explicitly
977// reading the body.
978TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13979 HttpRequestInfo request;
980 request.method = "GET";
981 request.url = GURL("http://www.foo.com/");
982 request.load_flags = 0;
983
[email protected]cb9bf6ca2011-01-28 13:15:27984 SessionDependencies session_deps;
985 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
986
[email protected]0b0bf032010-09-21 18:08:50987 // Note that because all these reads happen in the same
988 // StaticSocketDataProvider, it shows that the same socket is being reused for
989 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13990 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50991 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
992 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13993 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50994 MockRead("HTTP/1.1 302 Found\r\n"
995 "Content-Length: 0\r\n\r\n"),
996 MockRead("HTTP/1.1 302 Found\r\n"
997 "Content-Length: 5\r\n\r\n"
998 "hello"),
999 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1000 "Content-Length: 0\r\n\r\n"),
1001 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1002 "Content-Length: 5\r\n\r\n"
1003 "hello"),
[email protected]fc31d6a42010-06-24 18:05:131004 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1005 MockRead("hello"),
1006 };
1007 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1008 session_deps.socket_factory.AddSocketDataProvider(&data1);
1009
1010 MockRead data2_reads[] = {
1011 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
1012 };
1013 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1014 session_deps.socket_factory.AddSocketDataProvider(&data2);
1015
[email protected]0b0bf032010-09-21 18:08:501016 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1017 std::string response_lines[kNumUnreadBodies];
1018
1019 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:131020 TestCompletionCallback callback;
1021
1022 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1023
1024 int rv = trans->Start(&request, &callback, BoundNetLog());
1025 EXPECT_EQ(ERR_IO_PENDING, rv);
1026
1027 rv = callback.WaitForResult();
1028 EXPECT_EQ(OK, rv);
1029
1030 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:501031 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:131032
[email protected]0b0bf032010-09-21 18:08:501033 ASSERT_TRUE(response->headers != NULL);
1034 response_lines[i] = response->headers->GetStatusLine();
1035
1036 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:131037 }
[email protected]0b0bf032010-09-21 18:08:501038
1039 const char* const kStatusLines[] = {
1040 "HTTP/1.1 204 No Content",
1041 "HTTP/1.1 205 Reset Content",
1042 "HTTP/1.1 304 Not Modified",
1043 "HTTP/1.1 302 Found",
1044 "HTTP/1.1 302 Found",
1045 "HTTP/1.1 301 Moved Permanently",
1046 "HTTP/1.1 301 Moved Permanently",
1047 };
1048
1049 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1050 forgot_to_update_kStatusLines);
1051
1052 for (int i = 0; i < kNumUnreadBodies; ++i)
1053 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1054
1055 TestCompletionCallback callback;
1056 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1057 int rv = trans->Start(&request, &callback, BoundNetLog());
1058 EXPECT_EQ(ERR_IO_PENDING, rv);
1059 rv = callback.WaitForResult();
1060 EXPECT_EQ(OK, rv);
1061 const HttpResponseInfo* response = trans->GetResponseInfo();
1062 ASSERT_TRUE(response != NULL);
1063 ASSERT_TRUE(response->headers != NULL);
1064 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1065 std::string response_data;
1066 rv = ReadTransaction(trans.get(), &response_data);
1067 EXPECT_EQ(OK, rv);
1068 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131069}
1070
[email protected]038e9a32008-10-08 22:40:161071// Test the request-challenge-retry sequence for basic auth.
1072// (basic auth is the easiest to mock, because it has no randomness).
1073TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421074 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161075 request.method = "GET";
1076 request.url = GURL("http://www.google.com/");
1077 request.load_flags = 0;
1078
[email protected]cb9bf6ca2011-01-28 13:15:271079 SessionDependencies session_deps;
1080 scoped_ptr<HttpTransaction> trans(
1081 new HttpNetworkTransaction(CreateSession(&session_deps)));
1082
[email protected]f9ee6b52008-11-08 06:46:231083 MockWrite data_writes1[] = {
1084 MockWrite("GET / HTTP/1.1\r\n"
1085 "Host: www.google.com\r\n"
1086 "Connection: keep-alive\r\n\r\n"),
1087 };
1088
[email protected]038e9a32008-10-08 22:40:161089 MockRead data_reads1[] = {
1090 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1091 // Give a couple authenticate options (only the middle one is actually
1092 // supported).
[email protected]22927ad2009-09-21 19:56:191093 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161094 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1095 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1096 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1097 // Large content-length -- won't matter, as connection will be reset.
1098 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421099 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161100 };
1101
1102 // After calling trans->RestartWithAuth(), this is the request we should
1103 // be issuing -- the final header line contains the credentials.
1104 MockWrite data_writes2[] = {
1105 MockWrite("GET / HTTP/1.1\r\n"
1106 "Host: www.google.com\r\n"
1107 "Connection: keep-alive\r\n"
1108 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1109 };
1110
1111 // Lastly, the server responds with the actual content.
1112 MockRead data_reads2[] = {
1113 MockRead("HTTP/1.0 200 OK\r\n"),
1114 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1115 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421116 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161117 };
1118
[email protected]31a2bfe2010-02-09 08:03:391119 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1120 data_writes1, arraysize(data_writes1));
1121 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1122 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591123 session_deps.socket_factory.AddSocketDataProvider(&data1);
1124 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161125
1126 TestCompletionCallback callback1;
1127
[email protected]5a1d7ca2010-04-28 20:12:271128 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421129 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161130
1131 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421132 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161133
[email protected]1c773ea12009-04-28 19:58:421134 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161135 EXPECT_FALSE(response == NULL);
1136
1137 // The password prompt info should have been set in response->auth_challenge.
1138 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1139
[email protected]71e4573a2009-05-21 22:03:001140 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161141 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1142 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1143
1144 TestCompletionCallback callback2;
1145
[email protected]13c8a092010-07-29 06:15:441146 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421147 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161148
1149 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421150 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161151
1152 response = trans->GetResponseInfo();
1153 EXPECT_FALSE(response == NULL);
1154 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1155 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161156}
1157
[email protected]861fcd52009-08-26 02:33:461158TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:461159 HttpRequestInfo request;
1160 request.method = "GET";
1161 request.url = GURL("http://www.google.com/");
1162 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1163
[email protected]cb9bf6ca2011-01-28 13:15:271164 SessionDependencies session_deps;
1165 scoped_ptr<HttpTransaction> trans(
1166 new HttpNetworkTransaction(CreateSession(&session_deps)));
1167
[email protected]861fcd52009-08-26 02:33:461168 MockWrite data_writes[] = {
1169 MockWrite("GET / HTTP/1.1\r\n"
1170 "Host: www.google.com\r\n"
1171 "Connection: keep-alive\r\n\r\n"),
1172 };
1173
1174 MockRead data_reads[] = {
1175 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1176 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1177 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1178 // Large content-length -- won't matter, as connection will be reset.
1179 MockRead("Content-Length: 10000\r\n\r\n"),
1180 MockRead(false, ERR_FAILED),
1181 };
1182
[email protected]31a2bfe2010-02-09 08:03:391183 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1184 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591185 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461186 TestCompletionCallback callback;
1187
[email protected]5a1d7ca2010-04-28 20:12:271188 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461189 EXPECT_EQ(ERR_IO_PENDING, rv);
1190
1191 rv = callback.WaitForResult();
1192 EXPECT_EQ(0, rv);
1193
1194 const HttpResponseInfo* response = trans->GetResponseInfo();
1195 ASSERT_FALSE(response == NULL);
1196 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1197}
1198
[email protected]2d2697f92009-02-18 21:00:321199// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1200// connection.
1201TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]1c773ea12009-04-28 19:58:421202 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321203 request.method = "GET";
1204 request.url = GURL("http://www.google.com/");
1205 request.load_flags = 0;
1206
[email protected]cb9bf6ca2011-01-28 13:15:271207 SessionDependencies session_deps;
1208 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1209
[email protected]2d2697f92009-02-18 21:00:321210 MockWrite data_writes1[] = {
1211 MockWrite("GET / HTTP/1.1\r\n"
1212 "Host: www.google.com\r\n"
1213 "Connection: keep-alive\r\n\r\n"),
1214
1215 // After calling trans->RestartWithAuth(), this is the request we should
1216 // be issuing -- the final header line contains the credentials.
1217 MockWrite("GET / HTTP/1.1\r\n"
1218 "Host: www.google.com\r\n"
1219 "Connection: keep-alive\r\n"
1220 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1221 };
1222
1223 MockRead data_reads1[] = {
1224 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1225 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1226 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1227 MockRead("Content-Length: 14\r\n\r\n"),
1228 MockRead("Unauthorized\r\n"),
1229
1230 // Lastly, the server responds with the actual content.
1231 MockRead("HTTP/1.1 200 OK\r\n"),
1232 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501233 MockRead("Content-Length: 5\r\n\r\n"),
1234 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321235 };
1236
[email protected]2d0a4f92011-05-05 16:38:461237 // If there is a regression where we disconnect a Keep-Alive
1238 // connection during an auth roundtrip, we'll end up reading this.
1239 MockRead data_reads2[] = {
1240 MockRead(false, ERR_FAILED),
1241 };
1242
[email protected]31a2bfe2010-02-09 08:03:391243 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1244 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461245 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1246 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591247 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461248 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321249
1250 TestCompletionCallback callback1;
1251
[email protected]0b0bf032010-09-21 18:08:501252 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271253 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421254 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321255
1256 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421257 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321258
[email protected]1c773ea12009-04-28 19:58:421259 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321260 EXPECT_FALSE(response == NULL);
1261
1262 // The password prompt info should have been set in response->auth_challenge.
1263 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1264
[email protected]71e4573a2009-05-21 22:03:001265 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321266 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1267 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1268
1269 TestCompletionCallback callback2;
1270
[email protected]13c8a092010-07-29 06:15:441271 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421272 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321273
1274 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421275 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321276
1277 response = trans->GetResponseInfo();
[email protected]2d0a4f92011-05-05 16:38:461278 ASSERT_FALSE(response == NULL);
[email protected]2d2697f92009-02-18 21:00:321279 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501280 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321281}
1282
1283// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1284// connection and with no response body to drain.
1285TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:421286 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321287 request.method = "GET";
1288 request.url = GURL("http://www.google.com/");
1289 request.load_flags = 0;
1290
[email protected]cb9bf6ca2011-01-28 13:15:271291 SessionDependencies session_deps;
1292 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1293
[email protected]2d2697f92009-02-18 21:00:321294 MockWrite data_writes1[] = {
1295 MockWrite("GET / HTTP/1.1\r\n"
1296 "Host: www.google.com\r\n"
1297 "Connection: keep-alive\r\n\r\n"),
1298
1299 // After calling trans->RestartWithAuth(), this is the request we should
1300 // be issuing -- the final header line contains the credentials.
1301 MockWrite("GET / HTTP/1.1\r\n"
1302 "Host: www.google.com\r\n"
1303 "Connection: keep-alive\r\n"
1304 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1305 };
1306
[email protected]2d2697f92009-02-18 21:00:321307 MockRead data_reads1[] = {
1308 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1309 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311310 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321311
1312 // Lastly, the server responds with the actual content.
1313 MockRead("HTTP/1.1 200 OK\r\n"),
1314 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501315 MockRead("Content-Length: 5\r\n\r\n"),
1316 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321317 };
1318
[email protected]2d0a4f92011-05-05 16:38:461319 // An incorrect reconnect would cause this to be read.
1320 MockRead data_reads2[] = {
1321 MockRead(false, ERR_FAILED),
1322 };
1323
[email protected]31a2bfe2010-02-09 08:03:391324 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1325 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461326 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1327 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591328 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461329 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321330
1331 TestCompletionCallback callback1;
1332
[email protected]0b0bf032010-09-21 18:08:501333 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271334 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421335 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321336
1337 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421338 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321339
[email protected]1c773ea12009-04-28 19:58:421340 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321341 EXPECT_FALSE(response == NULL);
1342
1343 // The password prompt info should have been set in response->auth_challenge.
1344 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1345
[email protected]71e4573a2009-05-21 22:03:001346 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321347 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1348 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1349
1350 TestCompletionCallback callback2;
1351
[email protected]13c8a092010-07-29 06:15:441352 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421353 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321354
1355 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421356 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321357
1358 response = trans->GetResponseInfo();
[email protected]2d0a4f92011-05-05 16:38:461359 ASSERT_FALSE(response == NULL);
[email protected]2d2697f92009-02-18 21:00:321360 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501361 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321362}
1363
1364// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1365// connection and with a large response body to drain.
1366TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:421367 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321368 request.method = "GET";
1369 request.url = GURL("http://www.google.com/");
1370 request.load_flags = 0;
1371
[email protected]cb9bf6ca2011-01-28 13:15:271372 SessionDependencies session_deps;
1373 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1374
[email protected]2d2697f92009-02-18 21:00:321375 MockWrite data_writes1[] = {
1376 MockWrite("GET / HTTP/1.1\r\n"
1377 "Host: www.google.com\r\n"
1378 "Connection: keep-alive\r\n\r\n"),
1379
1380 // After calling trans->RestartWithAuth(), this is the request we should
1381 // be issuing -- the final header line contains the credentials.
1382 MockWrite("GET / HTTP/1.1\r\n"
1383 "Host: www.google.com\r\n"
1384 "Connection: keep-alive\r\n"
1385 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1386 };
1387
1388 // Respond with 5 kb of response body.
1389 std::string large_body_string("Unauthorized");
1390 large_body_string.append(5 * 1024, ' ');
1391 large_body_string.append("\r\n");
1392
1393 MockRead data_reads1[] = {
1394 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1395 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1396 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1397 // 5134 = 12 + 5 * 1024 + 2
1398 MockRead("Content-Length: 5134\r\n\r\n"),
1399 MockRead(true, large_body_string.data(), large_body_string.size()),
1400
1401 // Lastly, the server responds with the actual content.
1402 MockRead("HTTP/1.1 200 OK\r\n"),
1403 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501404 MockRead("Content-Length: 5\r\n\r\n"),
1405 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321406 };
1407
[email protected]2d0a4f92011-05-05 16:38:461408 // An incorrect reconnect would cause this to be read.
1409 MockRead data_reads2[] = {
1410 MockRead(false, ERR_FAILED),
1411 };
1412
[email protected]31a2bfe2010-02-09 08:03:391413 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1414 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461415 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1416 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591417 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461418 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321419
1420 TestCompletionCallback callback1;
1421
[email protected]0b0bf032010-09-21 18:08:501422 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271423 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421424 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321425
1426 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421427 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321428
[email protected]1c773ea12009-04-28 19:58:421429 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321430 EXPECT_FALSE(response == NULL);
1431
1432 // The password prompt info should have been set in response->auth_challenge.
1433 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1434
[email protected]71e4573a2009-05-21 22:03:001435 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321436 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1437 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1438
1439 TestCompletionCallback callback2;
1440
[email protected]13c8a092010-07-29 06:15:441441 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421442 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321443
1444 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421445 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321446
1447 response = trans->GetResponseInfo();
[email protected]2d0a4f92011-05-05 16:38:461448 ASSERT_FALSE(response == NULL);
[email protected]2d2697f92009-02-18 21:00:321449 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501450 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321451}
1452
1453// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311454// connection, but the server gets impatient and closes the connection.
1455TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:311456 HttpRequestInfo request;
1457 request.method = "GET";
1458 request.url = GURL("http://www.google.com/");
1459 request.load_flags = 0;
1460
[email protected]cb9bf6ca2011-01-28 13:15:271461 SessionDependencies session_deps;
1462 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1463
[email protected]11203f012009-11-12 23:02:311464 MockWrite data_writes1[] = {
1465 MockWrite("GET / HTTP/1.1\r\n"
1466 "Host: www.google.com\r\n"
1467 "Connection: keep-alive\r\n\r\n"),
1468 // This simulates the seemingly successful write to a closed connection
1469 // if the bug is not fixed.
1470 MockWrite("GET / HTTP/1.1\r\n"
1471 "Host: www.google.com\r\n"
1472 "Connection: keep-alive\r\n"
1473 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1474 };
1475
1476 MockRead data_reads1[] = {
1477 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1478 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1479 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1480 MockRead("Content-Length: 14\r\n\r\n"),
1481 // Tell MockTCPClientSocket to simulate the server closing the connection.
1482 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1483 MockRead("Unauthorized\r\n"),
1484 MockRead(false, OK), // The server closes the connection.
1485 };
1486
1487 // After calling trans->RestartWithAuth(), this is the request we should
1488 // be issuing -- the final header line contains the credentials.
1489 MockWrite data_writes2[] = {
1490 MockWrite("GET / HTTP/1.1\r\n"
1491 "Host: www.google.com\r\n"
1492 "Connection: keep-alive\r\n"
1493 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1494 };
1495
1496 // Lastly, the server responds with the actual content.
1497 MockRead data_reads2[] = {
1498 MockRead("HTTP/1.1 200 OK\r\n"),
1499 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501500 MockRead("Content-Length: 5\r\n\r\n"),
1501 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311502 };
1503
[email protected]31a2bfe2010-02-09 08:03:391504 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1505 data_writes1, arraysize(data_writes1));
1506 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1507 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311508 session_deps.socket_factory.AddSocketDataProvider(&data1);
1509 session_deps.socket_factory.AddSocketDataProvider(&data2);
1510
1511 TestCompletionCallback callback1;
1512
[email protected]0b0bf032010-09-21 18:08:501513 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271514 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311515 EXPECT_EQ(ERR_IO_PENDING, rv);
1516
1517 rv = callback1.WaitForResult();
1518 EXPECT_EQ(OK, rv);
1519
1520 const HttpResponseInfo* response = trans->GetResponseInfo();
1521 EXPECT_FALSE(response == NULL);
1522
1523 // The password prompt info should have been set in response->auth_challenge.
1524 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1525
1526 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1527 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1528 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1529
1530 TestCompletionCallback callback2;
1531
[email protected]13c8a092010-07-29 06:15:441532 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311533 EXPECT_EQ(ERR_IO_PENDING, rv);
1534
1535 rv = callback2.WaitForResult();
1536 EXPECT_EQ(OK, rv);
1537
1538 response = trans->GetResponseInfo();
1539 ASSERT_FALSE(response == NULL);
1540 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501541 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311542}
1543
[email protected]394816e92010-08-03 07:38:591544// Test the request-challenge-retry sequence for basic auth, over a connection
1545// that requires a restart when setting up an SSL tunnel.
1546TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
[email protected]394816e92010-08-03 07:38:591547 HttpRequestInfo request;
1548 request.method = "GET";
1549 request.url = GURL("https://www.google.com/");
1550 // when the no authentication data flag is set.
1551 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1552
[email protected]cb9bf6ca2011-01-28 13:15:271553 // Configure against proxy server "myproxy:70".
1554 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1555 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1556 session_deps.net_log = log.bound().net_log();
1557 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1558
[email protected]394816e92010-08-03 07:38:591559 // Since we have proxy, should try to establish tunnel.
1560 MockWrite data_writes1[] = {
1561 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1562 "Host: www.google.com\r\n"
1563 "Proxy-Connection: keep-alive\r\n\r\n"),
1564
1565 // After calling trans->RestartWithAuth(), this is the request we should
1566 // be issuing -- the final header line contains the credentials.
1567 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1568 "Host: www.google.com\r\n"
1569 "Proxy-Connection: keep-alive\r\n"
1570 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1571
1572 MockWrite("GET / HTTP/1.1\r\n"
1573 "Host: www.google.com\r\n"
1574 "Connection: keep-alive\r\n\r\n"),
1575 };
1576
1577 // The proxy responds to the connect with a 407, using a persistent
1578 // connection.
1579 MockRead data_reads1[] = {
1580 // No credentials.
1581 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1582 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1583 MockRead("Proxy-Connection: close\r\n\r\n"),
1584
1585 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1586
1587 MockRead("HTTP/1.1 200 OK\r\n"),
1588 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501589 MockRead("Content-Length: 5\r\n\r\n"),
1590 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591591 };
1592
1593 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1594 data_writes1, arraysize(data_writes1));
1595 session_deps.socket_factory.AddSocketDataProvider(&data1);
1596 SSLSocketDataProvider ssl(true, OK);
1597 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1598
1599 TestCompletionCallback callback1;
1600
[email protected]0b0bf032010-09-21 18:08:501601 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1602
[email protected]394816e92010-08-03 07:38:591603 int rv = trans->Start(&request, &callback1, log.bound());
1604 EXPECT_EQ(ERR_IO_PENDING, rv);
1605
1606 rv = callback1.WaitForResult();
1607 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401608 net::CapturingNetLog::EntryList entries;
1609 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:591610 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401611 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:591612 NetLog::PHASE_NONE);
1613 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401614 entries, pos,
[email protected]394816e92010-08-03 07:38:591615 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1616 NetLog::PHASE_NONE);
1617
1618 const HttpResponseInfo* response = trans->GetResponseInfo();
1619 ASSERT_FALSE(response == NULL);
1620
1621 EXPECT_EQ(407, response->headers->response_code());
1622 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1623
1624 // The password prompt info should have been set in response->auth_challenge.
1625 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1626
1627 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1628 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1629 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1630
1631 TestCompletionCallback callback2;
1632
1633 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1634 EXPECT_EQ(ERR_IO_PENDING, rv);
1635
1636 rv = callback2.WaitForResult();
1637 EXPECT_EQ(OK, rv);
1638
1639 response = trans->GetResponseInfo();
1640 ASSERT_FALSE(response == NULL);
1641
1642 EXPECT_TRUE(response->headers->IsKeepAlive());
1643 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501644 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591645 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1646
1647 // The password prompt info should not be set.
1648 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501649
1650 trans.reset();
[email protected]102e27c2011-02-23 01:01:311651 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:591652}
1653
[email protected]11203f012009-11-12 23:02:311654// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321655// proxy connection, when setting up an SSL tunnel.
1656TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
[email protected]cb9bf6ca2011-01-28 13:15:271657 HttpRequestInfo request;
1658 request.method = "GET";
1659 request.url = GURL("https://www.google.com/");
1660 // Ensure that proxy authentication is attempted even
1661 // when the no authentication data flag is set.
1662 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1663
[email protected]2d2697f92009-02-18 21:00:321664 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001665 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541666 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1667 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591668 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321669
[email protected]5695b8c2009-09-30 21:36:431670 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321671
[email protected]2d2697f92009-02-18 21:00:321672 // Since we have proxy, should try to establish tunnel.
1673 MockWrite data_writes1[] = {
1674 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451675 "Host: www.google.com\r\n"
1676 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321677
1678 // After calling trans->RestartWithAuth(), this is the request we should
1679 // be issuing -- the final header line contains the credentials.
1680 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1681 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451682 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321683 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1684 };
1685
1686 // The proxy responds to the connect with a 407, using a persistent
1687 // connection.
1688 MockRead data_reads1[] = {
1689 // No credentials.
1690 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1691 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1692 MockRead("Content-Length: 10\r\n\r\n"),
1693 MockRead("0123456789"),
1694
1695 // Wrong credentials (wrong password).
1696 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1697 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1698 MockRead("Content-Length: 10\r\n\r\n"),
1699 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421700 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321701 };
1702
[email protected]31a2bfe2010-02-09 08:03:391703 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1704 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591705 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321706
1707 TestCompletionCallback callback1;
1708
[email protected]dbb83db2010-05-11 18:13:391709 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421710 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321711
1712 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421713 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401714 net::CapturingNetLog::EntryList entries;
1715 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:391716 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401717 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:391718 NetLog::PHASE_NONE);
1719 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401720 entries, pos,
[email protected]dbb83db2010-05-11 18:13:391721 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1722 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321723
[email protected]1c773ea12009-04-28 19:58:421724 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321725 EXPECT_FALSE(response == NULL);
1726
1727 EXPECT_TRUE(response->headers->IsKeepAlive());
1728 EXPECT_EQ(407, response->headers->response_code());
1729 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421730 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321731
1732 // The password prompt info should have been set in response->auth_challenge.
1733 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1734
[email protected]71e4573a2009-05-21 22:03:001735 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321736 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1737 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1738
1739 TestCompletionCallback callback2;
1740
1741 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441742 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421743 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321744
1745 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421746 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321747
1748 response = trans->GetResponseInfo();
1749 EXPECT_FALSE(response == NULL);
1750
1751 EXPECT_TRUE(response->headers->IsKeepAlive());
1752 EXPECT_EQ(407, response->headers->response_code());
1753 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421754 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321755
1756 // The password prompt info should have been set in response->auth_challenge.
1757 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1758
[email protected]71e4573a2009-05-21 22:03:001759 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321760 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1761 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131762
[email protected]e60e47a2010-07-14 03:37:181763 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1764 // out of scope.
[email protected]102e27c2011-02-23 01:01:311765 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:321766}
1767
[email protected]a8e9b162009-03-12 00:06:441768// Test that we don't read the response body when we fail to establish a tunnel,
1769// even if the user cancels the proxy's auth attempt.
1770TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:271771 HttpRequestInfo request;
1772 request.method = "GET";
1773 request.url = GURL("https://www.google.com/");
1774 request.load_flags = 0;
1775
[email protected]a8e9b162009-03-12 00:06:441776 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001777 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441778
[email protected]e44de5d2009-06-05 20:12:451779 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441780
[email protected]5695b8c2009-09-30 21:36:431781 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441782
[email protected]a8e9b162009-03-12 00:06:441783 // Since we have proxy, should try to establish tunnel.
1784 MockWrite data_writes[] = {
1785 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451786 "Host: www.google.com\r\n"
1787 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441788 };
1789
1790 // The proxy responds to the connect with a 407.
1791 MockRead data_reads[] = {
1792 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1793 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1794 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421795 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441796 };
1797
[email protected]31a2bfe2010-02-09 08:03:391798 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1799 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591800 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441801
1802 TestCompletionCallback callback;
1803
[email protected]5a1d7ca2010-04-28 20:12:271804 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421805 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441806
1807 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421808 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441809
[email protected]1c773ea12009-04-28 19:58:421810 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441811 EXPECT_FALSE(response == NULL);
1812
1813 EXPECT_TRUE(response->headers->IsKeepAlive());
1814 EXPECT_EQ(407, response->headers->response_code());
1815 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421816 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441817
1818 std::string response_data;
1819 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421820 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181821
1822 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:311823 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:441824}
1825
[email protected]8fdbcd22010-05-05 02:54:521826// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1827// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1828TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:521829 HttpRequestInfo request;
1830 request.method = "GET";
1831 request.url = GURL("http://www.google.com/");
1832 request.load_flags = 0;
1833
[email protected]cb9bf6ca2011-01-28 13:15:271834 // We are using a DIRECT connection (i.e. no proxy) for this session.
1835 SessionDependencies session_deps;
1836 scoped_ptr<HttpTransaction> trans(
1837 new HttpNetworkTransaction(CreateSession(&session_deps)));
1838
[email protected]8fdbcd22010-05-05 02:54:521839 MockWrite data_writes1[] = {
1840 MockWrite("GET / HTTP/1.1\r\n"
1841 "Host: www.google.com\r\n"
1842 "Connection: keep-alive\r\n\r\n"),
1843 };
1844
1845 MockRead data_reads1[] = {
1846 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1847 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1848 // Large content-length -- won't matter, as connection will be reset.
1849 MockRead("Content-Length: 10000\r\n\r\n"),
1850 MockRead(false, ERR_FAILED),
1851 };
1852
1853 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1854 data_writes1, arraysize(data_writes1));
1855 session_deps.socket_factory.AddSocketDataProvider(&data1);
1856
1857 TestCompletionCallback callback;
1858
1859 int rv = trans->Start(&request, &callback, BoundNetLog());
1860 EXPECT_EQ(ERR_IO_PENDING, rv);
1861
1862 rv = callback.WaitForResult();
1863 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1864}
1865
[email protected]7a67a8152010-11-05 18:31:101866// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
1867// through a non-authenticating proxy. The request should fail with
1868// ERR_UNEXPECTED_PROXY_AUTH.
1869// Note that it is impossible to detect if an HTTP server returns a 407 through
1870// a non-authenticating proxy - there is nothing to indicate whether the
1871// response came from the proxy or the server, so it is treated as if the proxy
1872// issued the challenge.
1873TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:271874 HttpRequestInfo request;
1875 request.method = "GET";
1876 request.url = GURL("https://www.google.com/");
1877
[email protected]7a67a8152010-11-05 18:31:101878 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1879 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1880 session_deps.net_log = log.bound().net_log();
1881 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1882
[email protected]7a67a8152010-11-05 18:31:101883 // Since we have proxy, should try to establish tunnel.
1884 MockWrite data_writes1[] = {
1885 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1886 "Host: www.google.com\r\n"
1887 "Proxy-Connection: keep-alive\r\n\r\n"),
1888
1889 MockWrite("GET / HTTP/1.1\r\n"
1890 "Host: www.google.com\r\n"
1891 "Connection: keep-alive\r\n\r\n"),
1892 };
1893
1894 MockRead data_reads1[] = {
1895 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1896
1897 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
1898 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1899 MockRead("\r\n"),
1900 MockRead(false, OK),
1901 };
1902
1903 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1904 data_writes1, arraysize(data_writes1));
1905 session_deps.socket_factory.AddSocketDataProvider(&data1);
1906 SSLSocketDataProvider ssl(true, OK);
1907 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1908
1909 TestCompletionCallback callback1;
1910
1911 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1912
1913 int rv = trans->Start(&request, &callback1, log.bound());
1914 EXPECT_EQ(ERR_IO_PENDING, rv);
1915
1916 rv = callback1.WaitForResult();
1917 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
[email protected]b2fcd0e2010-12-01 15:19:401918 net::CapturingNetLog::EntryList entries;
1919 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:101920 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401921 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:101922 NetLog::PHASE_NONE);
1923 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401924 entries, pos,
[email protected]7a67a8152010-11-05 18:31:101925 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1926 NetLog::PHASE_NONE);
1927}
[email protected]2df19bb2010-08-25 20:13:461928
1929// Test a simple get through an HTTPS Proxy.
1930TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271931 HttpRequestInfo request;
1932 request.method = "GET";
1933 request.url = GURL("http://www.google.com/");
1934
[email protected]2df19bb2010-08-25 20:13:461935 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001936 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:461937 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1938 session_deps.net_log = log.bound().net_log();
1939 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1940
[email protected]2df19bb2010-08-25 20:13:461941 // Since we have proxy, should use full url
1942 MockWrite data_writes1[] = {
1943 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1944 "Host: www.google.com\r\n"
1945 "Proxy-Connection: keep-alive\r\n\r\n"),
1946 };
1947
1948 MockRead data_reads1[] = {
1949 MockRead("HTTP/1.1 200 OK\r\n"),
1950 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1951 MockRead("Content-Length: 100\r\n\r\n"),
1952 MockRead(false, OK),
1953 };
1954
1955 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1956 data_writes1, arraysize(data_writes1));
1957 session_deps.socket_factory.AddSocketDataProvider(&data1);
1958 SSLSocketDataProvider ssl(true, OK);
1959 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1960
1961 TestCompletionCallback callback1;
1962
[email protected]0b0bf032010-09-21 18:08:501963 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1964
[email protected]2df19bb2010-08-25 20:13:461965 int rv = trans->Start(&request, &callback1, log.bound());
1966 EXPECT_EQ(ERR_IO_PENDING, rv);
1967
1968 rv = callback1.WaitForResult();
1969 EXPECT_EQ(OK, rv);
1970
1971 const HttpResponseInfo* response = trans->GetResponseInfo();
1972 ASSERT_FALSE(response == NULL);
1973
1974 EXPECT_TRUE(response->headers->IsKeepAlive());
1975 EXPECT_EQ(200, response->headers->response_code());
1976 EXPECT_EQ(100, response->headers->GetContentLength());
1977 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1978
1979 // The password prompt info should not be set.
1980 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1981}
1982
[email protected]7642b5ae2010-09-01 20:55:171983// Test a SPDY get through an HTTPS Proxy.
1984TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271985 HttpRequestInfo request;
1986 request.method = "GET";
1987 request.url = GURL("http://www.google.com/");
1988 request.load_flags = 0;
1989
[email protected]7642b5ae2010-09-01 20:55:171990 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001991 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:171992 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1993 session_deps.net_log = log.bound().net_log();
1994 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1995
[email protected]7642b5ae2010-09-01 20:55:171996 // fetch http://www.google.com/ via SPDY
1997 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1998 false));
1999 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2000
2001 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2002 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2003 MockRead spdy_reads[] = {
2004 CreateMockRead(*resp),
2005 CreateMockRead(*data),
2006 MockRead(true, 0, 0),
2007 };
2008
2009 scoped_refptr<DelayedSocketData> spdy_data(
2010 new DelayedSocketData(
2011 1, // wait for one write to finish before reading.
2012 spdy_reads, arraysize(spdy_reads),
2013 spdy_writes, arraysize(spdy_writes)));
2014 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2015
2016 SSLSocketDataProvider ssl(true, OK);
2017 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2018 ssl.next_proto = "spdy/2";
2019 ssl.was_npn_negotiated = true;
2020 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2021
2022 TestCompletionCallback callback1;
2023
[email protected]0b0bf032010-09-21 18:08:502024 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2025
[email protected]7642b5ae2010-09-01 20:55:172026 int rv = trans->Start(&request, &callback1, log.bound());
2027 EXPECT_EQ(ERR_IO_PENDING, rv);
2028
2029 rv = callback1.WaitForResult();
2030 EXPECT_EQ(OK, rv);
2031
2032 const HttpResponseInfo* response = trans->GetResponseInfo();
2033 ASSERT_TRUE(response != NULL);
2034 ASSERT_TRUE(response->headers != NULL);
2035 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2036
2037 std::string response_data;
2038 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2039 EXPECT_EQ(net::kUploadData, response_data);
2040}
2041
[email protected]dc7bd1c52010-11-12 00:01:132042// Test a SPDY get through an HTTPS Proxy.
2043TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:272044 HttpRequestInfo request;
2045 request.method = "GET";
2046 request.url = GURL("http://www.google.com/");
2047 request.load_flags = 0;
2048
[email protected]dc7bd1c52010-11-12 00:01:132049 // Configure against https proxy server "proxy:70".
2050 SessionDependencies session_deps(
2051 ProxyService::CreateFixed("https://proxy:70"));
2052 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2053 session_deps.net_log = log.bound().net_log();
2054 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2055
[email protected]dc7bd1c52010-11-12 00:01:132056 // The first request will be a bare GET, the second request will be a
2057 // GET with a Proxy-Authorization header.
2058 scoped_ptr<spdy::SpdyFrame> req_get(
2059 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2060 const char* const kExtraAuthorizationHeaders[] = {
2061 "proxy-authorization",
2062 "Basic Zm9vOmJhcg==",
2063 };
2064 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
2065 ConstructSpdyGet(
2066 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
2067 false, 3, LOWEST, false));
2068 MockWrite spdy_writes[] = {
2069 CreateMockWrite(*req_get, 1),
2070 CreateMockWrite(*req_get_authorization, 4),
2071 };
2072
2073 // The first response is a 407 proxy authentication challenge, and the second
2074 // response will be a 200 response since the second request includes a valid
2075 // Authorization header.
2076 const char* const kExtraAuthenticationHeaders[] = {
2077 "Proxy-Authenticate",
2078 "Basic realm=\"MyRealm1\""
2079 };
2080 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2081 ConstructSpdySynReplyError(
2082 "407 Proxy Authentication Required",
2083 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2084 1));
2085 scoped_ptr<spdy::SpdyFrame> body_authentication(
2086 ConstructSpdyBodyFrame(1, true));
2087 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2088 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2089 MockRead spdy_reads[] = {
2090 CreateMockRead(*resp_authentication, 2),
2091 CreateMockRead(*body_authentication, 3),
2092 CreateMockRead(*resp_data, 5),
2093 CreateMockRead(*body_data, 6),
2094 MockRead(true, 0, 7),
2095 };
2096
2097 scoped_refptr<OrderedSocketData> data(
2098 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2099 spdy_writes, arraysize(spdy_writes)));
2100 session_deps.socket_factory.AddSocketDataProvider(data);
2101
2102 SSLSocketDataProvider ssl(true, OK);
2103 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2104 ssl.next_proto = "spdy/2";
2105 ssl.was_npn_negotiated = true;
2106 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2107
2108 TestCompletionCallback callback1;
2109
2110 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2111
2112 int rv = trans->Start(&request, &callback1, log.bound());
2113 EXPECT_EQ(ERR_IO_PENDING, rv);
2114
2115 rv = callback1.WaitForResult();
2116 EXPECT_EQ(OK, rv);
2117
2118 const HttpResponseInfo* const response = trans->GetResponseInfo();
2119
2120 ASSERT_TRUE(response != NULL);
2121 ASSERT_TRUE(response->headers != NULL);
2122 EXPECT_EQ(407, response->headers->response_code());
2123 EXPECT_TRUE(response->was_fetched_via_spdy);
2124
2125 // The password prompt info should have been set in response->auth_challenge.
2126 ASSERT_TRUE(response->auth_challenge.get() != NULL);
2127 EXPECT_TRUE(response->auth_challenge->is_proxy);
2128 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2129 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2130 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2131
2132 TestCompletionCallback callback2;
2133
2134 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2135 EXPECT_EQ(ERR_IO_PENDING, rv);
2136
2137 rv = callback2.WaitForResult();
2138 EXPECT_EQ(OK, rv);
2139
2140 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2141
2142 ASSERT_TRUE(response_restart != NULL);
2143 ASSERT_TRUE(response_restart->headers != NULL);
2144 EXPECT_EQ(200, response_restart->headers->response_code());
2145 // The password prompt info should not be set.
2146 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2147}
2148
[email protected]d9da5fe2010-10-13 22:37:162149// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2150TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272151 HttpRequestInfo request;
2152 request.method = "GET";
2153 request.url = GURL("https://www.google.com/");
2154 request.load_flags = 0;
2155
[email protected]d9da5fe2010-10-13 22:37:162156 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002157 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162158 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2159 session_deps.net_log = log.bound().net_log();
2160 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2161
2162 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2163
[email protected]d9da5fe2010-10-13 22:37:162164 // CONNECT to www.google.com:443 via SPDY
2165 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2166 // fetch https://www.google.com/ via HTTP
2167
2168 const char get[] = "GET / HTTP/1.1\r\n"
2169 "Host: www.google.com\r\n"
2170 "Connection: keep-alive\r\n\r\n";
2171 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2172 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2173 MockWrite spdy_writes[] = {
2174 CreateMockWrite(*connect, 1),
2175 CreateMockWrite(*wrapped_get, 3)
2176 };
2177
2178 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2179 const char resp[] = "HTTP/1.1 200 OK\r\n"
2180 "Content-Length: 10\r\n\r\n";
2181
2182 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2183 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2184 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2185 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2186 MockRead spdy_reads[] = {
2187 CreateMockRead(*conn_resp, 2, true),
2188 CreateMockRead(*wrapped_get_resp, 4, true),
2189 CreateMockRead(*wrapped_body, 5, true),
2190 CreateMockRead(*wrapped_body, 6, true),
2191 MockRead(true, 0, 7),
2192 };
2193
2194 scoped_refptr<OrderedSocketData> spdy_data(
2195 new OrderedSocketData(
2196 spdy_reads, arraysize(spdy_reads),
2197 spdy_writes, arraysize(spdy_writes)));
2198 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2199
2200 SSLSocketDataProvider ssl(true, OK);
2201 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2202 ssl.next_proto = "spdy/2";
2203 ssl.was_npn_negotiated = true;
2204 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2205 SSLSocketDataProvider ssl2(true, OK);
2206 ssl2.was_npn_negotiated = false;
2207 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2208
2209 TestCompletionCallback callback1;
2210
2211 int rv = trans->Start(&request, &callback1, log.bound());
2212 EXPECT_EQ(ERR_IO_PENDING, rv);
2213
2214 rv = callback1.WaitForResult();
2215 EXPECT_EQ(OK, rv);
2216
2217 const HttpResponseInfo* response = trans->GetResponseInfo();
2218 ASSERT_TRUE(response != NULL);
2219 ASSERT_TRUE(response->headers != NULL);
2220 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2221
2222 std::string response_data;
2223 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2224 EXPECT_EQ("1234567890", response_data);
2225}
2226
2227// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2228TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272229 HttpRequestInfo request;
2230 request.method = "GET";
2231 request.url = GURL("https://www.google.com/");
2232 request.load_flags = 0;
2233
[email protected]d9da5fe2010-10-13 22:37:162234 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002235 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162236 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2237 session_deps.net_log = log.bound().net_log();
2238 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2239
2240 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2241
[email protected]d9da5fe2010-10-13 22:37:162242 // CONNECT to www.google.com:443 via SPDY
2243 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2244 // fetch https://www.google.com/ via SPDY
2245 const char* const kMyUrl = "https://www.google.com/";
2246 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2247 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2248 MockWrite spdy_writes[] = {
2249 CreateMockWrite(*connect, 1),
2250 CreateMockWrite(*wrapped_get, 3)
2251 };
2252
2253 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2254 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2255 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2256 ConstructWrappedSpdyFrame(get_resp, 1));
2257 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2258 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2259 MockRead spdy_reads[] = {
2260 CreateMockRead(*conn_resp, 2, true),
2261 CreateMockRead(*wrapped_get_resp, 4, true),
2262 CreateMockRead(*wrapped_body, 5, true),
2263 MockRead(true, 0, 1),
2264 };
2265
2266 scoped_refptr<OrderedSocketData> spdy_data(
2267 new OrderedSocketData(
2268 spdy_reads, arraysize(spdy_reads),
2269 spdy_writes, arraysize(spdy_writes)));
2270 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2271
2272 SSLSocketDataProvider ssl(true, OK);
2273 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2274 ssl.next_proto = "spdy/2";
2275 ssl.was_npn_negotiated = true;
2276 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2277 SSLSocketDataProvider ssl2(true, OK);
2278 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2279 ssl2.next_proto = "spdy/2";
2280 ssl2.was_npn_negotiated = true;
2281 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2282
2283 TestCompletionCallback callback1;
2284
2285 int rv = trans->Start(&request, &callback1, log.bound());
2286 EXPECT_EQ(ERR_IO_PENDING, rv);
2287
2288 rv = callback1.WaitForResult();
2289 EXPECT_EQ(OK, rv);
2290
2291 const HttpResponseInfo* response = trans->GetResponseInfo();
2292 ASSERT_TRUE(response != NULL);
2293 ASSERT_TRUE(response->headers != NULL);
2294 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2295
2296 std::string response_data;
2297 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2298 EXPECT_EQ(net::kUploadData, response_data);
2299}
2300
2301// Test a SPDY CONNECT failure through an HTTPS Proxy.
2302TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272303 HttpRequestInfo request;
2304 request.method = "GET";
2305 request.url = GURL("https://www.google.com/");
2306 request.load_flags = 0;
2307
[email protected]d9da5fe2010-10-13 22:37:162308 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002309 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162310 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2311 session_deps.net_log = log.bound().net_log();
2312 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2313
2314 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2315
[email protected]d9da5fe2010-10-13 22:37:162316 // CONNECT to www.google.com:443 via SPDY
2317 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2318 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2319
2320 MockWrite spdy_writes[] = {
2321 CreateMockWrite(*connect, 1),
2322 CreateMockWrite(*get, 3),
2323 };
2324
2325 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2326 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2327 MockRead spdy_reads[] = {
2328 CreateMockRead(*resp, 2, true),
2329 MockRead(true, 0, 4),
2330 };
2331
2332 scoped_refptr<OrderedSocketData> spdy_data(
2333 new OrderedSocketData(
2334 spdy_reads, arraysize(spdy_reads),
2335 spdy_writes, arraysize(spdy_writes)));
2336 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2337
2338 SSLSocketDataProvider ssl(true, OK);
2339 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2340 ssl.next_proto = "spdy/2";
2341 ssl.was_npn_negotiated = true;
2342 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2343 SSLSocketDataProvider ssl2(true, OK);
2344 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2345 ssl2.next_proto = "spdy/2";
2346 ssl2.was_npn_negotiated = true;
2347 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2348
2349 TestCompletionCallback callback1;
2350
2351 int rv = trans->Start(&request, &callback1, log.bound());
2352 EXPECT_EQ(ERR_IO_PENDING, rv);
2353
2354 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292355 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162356
2357 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]511f6f52010-12-17 03:58:292358 ASSERT_FALSE(response == NULL);
2359 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162360}
2361
[email protected]2df19bb2010-08-25 20:13:462362// Test the challenge-response-retry sequence through an HTTPS Proxy
2363TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462364 HttpRequestInfo request;
2365 request.method = "GET";
2366 request.url = GURL("http://www.google.com/");
2367 // when the no authentication data flag is set.
2368 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2369
[email protected]cb9bf6ca2011-01-28 13:15:272370 // Configure against https proxy server "proxy:70".
2371 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
2372 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2373 session_deps.net_log = log.bound().net_log();
2374 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2375
[email protected]2df19bb2010-08-25 20:13:462376 // Since we have proxy, should use full url
2377 MockWrite data_writes1[] = {
2378 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2379 "Host: www.google.com\r\n"
2380 "Proxy-Connection: keep-alive\r\n\r\n"),
2381
2382 // After calling trans->RestartWithAuth(), this is the request we should
2383 // be issuing -- the final header line contains the credentials.
2384 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2385 "Host: www.google.com\r\n"
2386 "Proxy-Connection: keep-alive\r\n"
2387 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2388 };
2389
2390 // The proxy responds to the GET with a 407, using a persistent
2391 // connection.
2392 MockRead data_reads1[] = {
2393 // No credentials.
2394 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2395 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2396 MockRead("Proxy-Connection: keep-alive\r\n"),
2397 MockRead("Content-Length: 0\r\n\r\n"),
2398
2399 MockRead("HTTP/1.1 200 OK\r\n"),
2400 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2401 MockRead("Content-Length: 100\r\n\r\n"),
2402 MockRead(false, OK),
2403 };
2404
2405 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2406 data_writes1, arraysize(data_writes1));
2407 session_deps.socket_factory.AddSocketDataProvider(&data1);
2408 SSLSocketDataProvider ssl(true, OK);
2409 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2410
2411 TestCompletionCallback callback1;
2412
[email protected]0b0bf032010-09-21 18:08:502413 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2414
[email protected]2df19bb2010-08-25 20:13:462415 int rv = trans->Start(&request, &callback1, log.bound());
2416 EXPECT_EQ(ERR_IO_PENDING, rv);
2417
2418 rv = callback1.WaitForResult();
2419 EXPECT_EQ(OK, rv);
2420
2421 const HttpResponseInfo* response = trans->GetResponseInfo();
2422 ASSERT_FALSE(response == NULL);
2423
2424 EXPECT_EQ(407, response->headers->response_code());
2425 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2426
2427 // The password prompt info should have been set in response->auth_challenge.
2428 ASSERT_FALSE(response->auth_challenge.get() == NULL);
2429
2430 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2431 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2432 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2433
2434 TestCompletionCallback callback2;
2435
2436 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2437 EXPECT_EQ(ERR_IO_PENDING, rv);
2438
2439 rv = callback2.WaitForResult();
2440 EXPECT_EQ(OK, rv);
2441
2442 response = trans->GetResponseInfo();
2443 ASSERT_FALSE(response == NULL);
2444
2445 EXPECT_TRUE(response->headers->IsKeepAlive());
2446 EXPECT_EQ(200, response->headers->response_code());
2447 EXPECT_EQ(100, response->headers->GetContentLength());
2448 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2449
2450 // The password prompt info should not be set.
2451 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2452}
2453
[email protected]ff007e162009-05-23 09:13:152454void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082455 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422456 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082457 request.method = "GET";
2458 request.url = GURL("https://www.google.com/");
2459 request.load_flags = 0;
2460
[email protected]cb9bf6ca2011-01-28 13:15:272461 // Configure against proxy server "myproxy:70".
2462 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2463
2464 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2465
[email protected]c744cf22009-02-27 07:28:082466 // Since we have proxy, should try to establish tunnel.
2467 MockWrite data_writes[] = {
2468 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452469 "Host: www.google.com\r\n"
2470 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082471 };
2472
2473 MockRead data_reads[] = {
2474 status,
2475 MockRead("Content-Length: 10\r\n\r\n"),
2476 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422477 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082478 };
2479
[email protected]31a2bfe2010-02-09 08:03:392480 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2481 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592482 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082483
2484 TestCompletionCallback callback;
2485
[email protected]0b0bf032010-09-21 18:08:502486 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2487
[email protected]5a1d7ca2010-04-28 20:12:272488 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422489 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082490
2491 rv = callback.WaitForResult();
2492 EXPECT_EQ(expected_status, rv);
2493}
2494
[email protected]ff007e162009-05-23 09:13:152495void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082496 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422497 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082498}
2499
2500TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2501 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2502}
2503
2504TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2505 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2506}
2507
2508TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2509 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2510}
2511
2512TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2513 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2514}
2515
2516TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2517 ConnectStatusHelper(
2518 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2519}
2520
2521TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2522 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2523}
2524
2525TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2526 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2527}
2528
2529TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2530 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2531}
2532
2533TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2534 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2535}
2536
2537TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2538 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2539}
2540
2541TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2542 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2543}
2544
2545TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2546 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2547}
2548
2549TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2550 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2551}
2552
2553TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2554 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2555}
2556
2557TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2558 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2559}
2560
2561TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2562 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2563}
2564
2565TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2566 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2567}
2568
2569TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2570 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2571}
2572
2573TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2574 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2575}
2576
2577TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2578 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2579}
2580
2581TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2582 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2583}
2584
2585TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2586 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2587}
2588
2589TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2590 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2591}
2592
2593TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2594 ConnectStatusHelperWithExpectedStatus(
2595 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542596 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082597}
2598
2599TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2600 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2601}
2602
2603TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2604 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2605}
2606
2607TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2608 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2609}
2610
2611TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2612 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2613}
2614
2615TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2616 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2617}
2618
2619TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2620 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2621}
2622
2623TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2624 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2625}
2626
2627TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2628 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2629}
2630
2631TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2632 ConnectStatusHelper(
2633 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2634}
2635
2636TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2637 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2638}
2639
2640TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2641 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2642}
2643
2644TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2645 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2646}
2647
2648TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2649 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2650}
2651
2652TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2653 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2654}
2655
2656TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2657 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2658}
2659
2660TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2661 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2662}
2663
[email protected]038e9a32008-10-08 22:40:162664// Test the flow when both the proxy server AND origin server require
2665// authentication. Again, this uses basic auth for both since that is
2666// the simplest to mock.
2667TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272668 HttpRequestInfo request;
2669 request.method = "GET";
2670 request.url = GURL("http://www.google.com/");
2671 request.load_flags = 0;
2672
[email protected]81cdfcd2010-10-16 00:49:002673 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012674
[email protected]038e9a32008-10-08 22:40:162675 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422676 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432677 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162678
[email protected]f9ee6b52008-11-08 06:46:232679 MockWrite data_writes1[] = {
2680 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2681 "Host: www.google.com\r\n"
2682 "Proxy-Connection: keep-alive\r\n\r\n"),
2683 };
2684
[email protected]038e9a32008-10-08 22:40:162685 MockRead data_reads1[] = {
2686 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2687 // Give a couple authenticate options (only the middle one is actually
2688 // supported).
[email protected]22927ad2009-09-21 19:56:192689 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162690 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2691 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2692 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2693 // Large content-length -- won't matter, as connection will be reset.
2694 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422695 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162696 };
2697
2698 // After calling trans->RestartWithAuth() the first time, this is the
2699 // request we should be issuing -- the final header line contains the
2700 // proxy's credentials.
2701 MockWrite data_writes2[] = {
2702 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2703 "Host: www.google.com\r\n"
2704 "Proxy-Connection: keep-alive\r\n"
2705 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2706 };
2707
2708 // Now the proxy server lets the request pass through to origin server.
2709 // The origin server responds with a 401.
2710 MockRead data_reads2[] = {
2711 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2712 // Note: We are using the same realm-name as the proxy server. This is
2713 // completely valid, as realms are unique across hosts.
2714 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2715 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2716 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422717 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162718 };
2719
2720 // After calling trans->RestartWithAuth() the second time, we should send
2721 // the credentials for both the proxy and origin server.
2722 MockWrite data_writes3[] = {
2723 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2724 "Host: www.google.com\r\n"
2725 "Proxy-Connection: keep-alive\r\n"
2726 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2727 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2728 };
2729
2730 // Lastly we get the desired content.
2731 MockRead data_reads3[] = {
2732 MockRead("HTTP/1.0 200 OK\r\n"),
2733 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2734 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422735 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162736 };
2737
[email protected]31a2bfe2010-02-09 08:03:392738 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2739 data_writes1, arraysize(data_writes1));
2740 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2741 data_writes2, arraysize(data_writes2));
2742 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2743 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592744 session_deps.socket_factory.AddSocketDataProvider(&data1);
2745 session_deps.socket_factory.AddSocketDataProvider(&data2);
2746 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162747
2748 TestCompletionCallback callback1;
2749
[email protected]5a1d7ca2010-04-28 20:12:272750 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422751 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162752
2753 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422754 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162755
[email protected]1c773ea12009-04-28 19:58:422756 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162757 EXPECT_FALSE(response == NULL);
2758
2759 // The password prompt info should have been set in response->auth_challenge.
2760 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2761
[email protected]71e4573a2009-05-21 22:03:002762 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162763 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2764 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2765
2766 TestCompletionCallback callback2;
2767
[email protected]13c8a092010-07-29 06:15:442768 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422769 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162770
2771 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422772 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162773
2774 response = trans->GetResponseInfo();
2775 EXPECT_FALSE(response == NULL);
2776 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2777
[email protected]71e4573a2009-05-21 22:03:002778 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162779 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2780 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2781
2782 TestCompletionCallback callback3;
2783
[email protected]13c8a092010-07-29 06:15:442784 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422785 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162786
2787 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422788 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162789
2790 response = trans->GetResponseInfo();
2791 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2792 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162793}
[email protected]4ddaf2502008-10-23 18:26:192794
[email protected]ea9dc9a2009-09-05 00:43:322795// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2796// can't hook into its internals to cause it to generate predictable NTLM
2797// authorization headers.
2798#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292799// The NTLM authentication unit tests were generated by capturing the HTTP
2800// requests and responses using Fiddler 2 and inspecting the generated random
2801// bytes in the debugger.
2802
2803// Enter the correct password and authenticate successfully.
2804TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422805 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242806 request.method = "GET";
2807 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2808 request.load_flags = 0;
2809
[email protected]cb9bf6ca2011-01-28 13:15:272810 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2811 MockGetHostName);
2812 SessionDependencies session_deps;
2813 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2814
[email protected]3f918782009-02-28 01:29:242815 MockWrite data_writes1[] = {
2816 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2817 "Host: 172.22.68.17\r\n"
2818 "Connection: keep-alive\r\n\r\n"),
2819 };
2820
2821 MockRead data_reads1[] = {
2822 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042823 // Negotiate and NTLM are often requested together. However, we only want
2824 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2825 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242826 MockRead("WWW-Authenticate: NTLM\r\n"),
2827 MockRead("Connection: close\r\n"),
2828 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362829 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242830 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422831 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242832 };
2833
2834 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222835 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242836 // request we should be issuing -- the final header line contains a Type
2837 // 1 message.
2838 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2839 "Host: 172.22.68.17\r\n"
2840 "Connection: keep-alive\r\n"
2841 "Authorization: NTLM "
2842 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2843
2844 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2845 // (the credentials for the origin server). The second request continues
2846 // on the same connection.
2847 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2848 "Host: 172.22.68.17\r\n"
2849 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292850 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2851 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2852 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2853 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2854 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242855 };
2856
2857 MockRead data_reads2[] = {
2858 // The origin server responds with a Type 2 message.
2859 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2860 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292861 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242862 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2863 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2864 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2865 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2866 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2867 "BtAAAAAAA=\r\n"),
2868 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362869 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242870 MockRead("You are not authorized to view this page\r\n"),
2871
2872 // Lastly we get the desired content.
2873 MockRead("HTTP/1.1 200 OK\r\n"),
2874 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2875 MockRead("Content-Length: 13\r\n\r\n"),
2876 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422877 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242878 };
2879
[email protected]31a2bfe2010-02-09 08:03:392880 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2881 data_writes1, arraysize(data_writes1));
2882 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2883 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592884 session_deps.socket_factory.AddSocketDataProvider(&data1);
2885 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242886
2887 TestCompletionCallback callback1;
2888
[email protected]0b0bf032010-09-21 18:08:502889 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2890
[email protected]5a1d7ca2010-04-28 20:12:272891 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422892 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242893
2894 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422895 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242896
[email protected]0757e7702009-03-27 04:00:222897 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2898
[email protected]1c773ea12009-04-28 19:58:422899 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]10af5fe72011-01-31 16:17:252900 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:242901
[email protected]aef04272010-06-28 18:03:042902 // The password prompt info should have been set in
2903 // response->auth_challenge.
[email protected]10af5fe72011-01-31 16:17:252904 ASSERT_FALSE(response->auth_challenge.get() == NULL);
[email protected]3f918782009-02-28 01:29:242905
[email protected]71e4573a2009-05-21 22:03:002906 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242907 EXPECT_EQ(L"", response->auth_challenge->realm);
2908 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2909
[email protected]10af5fe72011-01-31 16:17:252910 TestCompletionCallback callback2;
2911
2912 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback2);
2913 EXPECT_EQ(ERR_IO_PENDING, rv);
2914
2915 rv = callback2.WaitForResult();
2916 EXPECT_EQ(OK, rv);
2917
2918 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2919
2920 response = trans->GetResponseInfo();
2921 ASSERT_TRUE(response != NULL);
2922
2923 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2924
[email protected]0757e7702009-03-27 04:00:222925 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242926
[email protected]10af5fe72011-01-31 16:17:252927 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:422928 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242929
[email protected]0757e7702009-03-27 04:00:222930 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422931 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242932
2933 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042934 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242935 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2936 EXPECT_EQ(13, response->headers->GetContentLength());
2937}
2938
[email protected]385a4672009-03-11 22:21:292939// Enter a wrong password, and then the correct one.
2940TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422941 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292942 request.method = "GET";
2943 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2944 request.load_flags = 0;
2945
[email protected]cb9bf6ca2011-01-28 13:15:272946 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
2947 MockGetHostName);
2948 SessionDependencies session_deps;
2949 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2950
[email protected]385a4672009-03-11 22:21:292951 MockWrite data_writes1[] = {
2952 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2953 "Host: 172.22.68.17\r\n"
2954 "Connection: keep-alive\r\n\r\n"),
2955 };
2956
2957 MockRead data_reads1[] = {
2958 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042959 // Negotiate and NTLM are often requested together. However, we only want
2960 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2961 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292962 MockRead("WWW-Authenticate: NTLM\r\n"),
2963 MockRead("Connection: close\r\n"),
2964 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362965 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292966 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422967 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292968 };
2969
2970 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222971 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292972 // request we should be issuing -- the final header line contains a Type
2973 // 1 message.
2974 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2975 "Host: 172.22.68.17\r\n"
2976 "Connection: keep-alive\r\n"
2977 "Authorization: NTLM "
2978 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2979
2980 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2981 // (the credentials for the origin server). The second request continues
2982 // on the same connection.
2983 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2984 "Host: 172.22.68.17\r\n"
2985 "Connection: keep-alive\r\n"
2986 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2987 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2988 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2989 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2990 "4Ww7b7E=\r\n\r\n"),
2991 };
2992
2993 MockRead data_reads2[] = {
2994 // The origin server responds with a Type 2 message.
2995 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2996 MockRead("WWW-Authenticate: NTLM "
2997 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2998 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2999 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3000 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3001 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3002 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3003 "BtAAAAAAA=\r\n"),
3004 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363005 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293006 MockRead("You are not authorized to view this page\r\n"),
3007
3008 // Wrong password.
3009 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:293010 MockRead("WWW-Authenticate: NTLM\r\n"),
3011 MockRead("Connection: close\r\n"),
3012 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363013 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293014 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:423015 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293016 };
3017
3018 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:223019 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293020 // request we should be issuing -- the final header line contains a Type
3021 // 1 message.
3022 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3023 "Host: 172.22.68.17\r\n"
3024 "Connection: keep-alive\r\n"
3025 "Authorization: NTLM "
3026 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3027
3028 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3029 // (the credentials for the origin server). The second request continues
3030 // on the same connection.
3031 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3032 "Host: 172.22.68.17\r\n"
3033 "Connection: keep-alive\r\n"
3034 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3035 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3036 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
3037 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
3038 "+4MUm7c=\r\n\r\n"),
3039 };
3040
3041 MockRead data_reads3[] = {
3042 // The origin server responds with a Type 2 message.
3043 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3044 MockRead("WWW-Authenticate: NTLM "
3045 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
3046 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3047 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3048 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3049 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3050 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3051 "BtAAAAAAA=\r\n"),
3052 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363053 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293054 MockRead("You are not authorized to view this page\r\n"),
3055
3056 // Lastly we get the desired content.
3057 MockRead("HTTP/1.1 200 OK\r\n"),
3058 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3059 MockRead("Content-Length: 13\r\n\r\n"),
3060 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:423061 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:293062 };
3063
[email protected]31a2bfe2010-02-09 08:03:393064 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3065 data_writes1, arraysize(data_writes1));
3066 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3067 data_writes2, arraysize(data_writes2));
3068 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3069 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593070 session_deps.socket_factory.AddSocketDataProvider(&data1);
3071 session_deps.socket_factory.AddSocketDataProvider(&data2);
3072 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:293073
3074 TestCompletionCallback callback1;
3075
[email protected]0b0bf032010-09-21 18:08:503076 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3077
[email protected]5a1d7ca2010-04-28 20:12:273078 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423079 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293080
3081 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423082 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293083
[email protected]0757e7702009-03-27 04:00:223084 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293085
[email protected]1c773ea12009-04-28 19:58:423086 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:293087 EXPECT_FALSE(response == NULL);
3088
3089 // The password prompt info should have been set in response->auth_challenge.
3090 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3091
[email protected]71e4573a2009-05-21 22:03:003092 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:293093 EXPECT_EQ(L"", response->auth_challenge->realm);
3094 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3095
[email protected]10af5fe72011-01-31 16:17:253096 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:293097
[email protected]0757e7702009-03-27 04:00:223098 // Enter the wrong password.
[email protected]10af5fe72011-01-31 16:17:253099 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback2);
[email protected]1c773ea12009-04-28 19:58:423100 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293101
[email protected]10af5fe72011-01-31 16:17:253102 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423103 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293104
[email protected]0757e7702009-03-27 04:00:223105 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:253106 TestCompletionCallback callback3;
3107 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:423108 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:253109 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423110 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223111 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3112
3113 response = trans->GetResponseInfo();
[email protected]10af5fe72011-01-31 16:17:253114 ASSERT_TRUE(response != NULL);
[email protected]0757e7702009-03-27 04:00:223115
3116 // The password prompt info should have been set in response->auth_challenge.
3117 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3118
[email protected]71e4573a2009-05-21 22:03:003119 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:223120 EXPECT_EQ(L"", response->auth_challenge->realm);
3121 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3122
[email protected]10af5fe72011-01-31 16:17:253123 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:223124
3125 // Now enter the right password.
[email protected]10af5fe72011-01-31 16:17:253126 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback4);
3127 EXPECT_EQ(ERR_IO_PENDING, rv);
3128
3129 rv = callback4.WaitForResult();
3130 EXPECT_EQ(OK, rv);
3131
3132 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3133
3134 TestCompletionCallback callback5;
3135
3136 // One more roundtrip
3137 rv = trans->RestartWithAuth(string16(), string16(), &callback5);
[email protected]1c773ea12009-04-28 19:58:423138 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223139
3140 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423141 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223142
[email protected]385a4672009-03-11 22:21:293143 response = trans->GetResponseInfo();
3144 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3145 EXPECT_EQ(13, response->headers->GetContentLength());
3146}
[email protected]ea9dc9a2009-09-05 00:43:323147#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293148
[email protected]4ddaf2502008-10-23 18:26:193149// Test reading a server response which has only headers, and no body.
3150// After some maximum number of bytes is consumed, the transaction should
3151// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3152TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423153 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193154 request.method = "GET";
3155 request.url = GURL("http://www.google.com/");
3156 request.load_flags = 0;
3157
[email protected]cb9bf6ca2011-01-28 13:15:273158 SessionDependencies session_deps;
3159 scoped_ptr<HttpTransaction> trans(
3160 new HttpNetworkTransaction(CreateSession(&session_deps)));
3161
[email protected]b75b7b2f2009-10-06 00:54:533162 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433163 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533164 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193165
3166 MockRead data_reads[] = {
3167 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433168 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193169 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423170 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193171 };
[email protected]31a2bfe2010-02-09 08:03:393172 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593173 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193174
3175 TestCompletionCallback callback;
3176
[email protected]5a1d7ca2010-04-28 20:12:273177 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423178 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193179
3180 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423181 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193182
[email protected]1c773ea12009-04-28 19:58:423183 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193184 EXPECT_TRUE(response == NULL);
3185}
[email protected]f4e426b2008-11-05 00:24:493186
3187// Make sure that we don't try to reuse a TCPClientSocket when failing to
3188// establish tunnel.
3189// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]ab739042011-04-07 15:22:283190TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273191 HttpRequestInfo request;
3192 request.method = "GET";
3193 request.url = GURL("https://www.google.com/");
3194 request.load_flags = 0;
3195
[email protected]f4e426b2008-11-05 00:24:493196 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003197 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013198
[email protected]228ff742009-06-05 01:19:593199 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493200
[email protected]5695b8c2009-09-30 21:36:433201 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493202
[email protected]f4e426b2008-11-05 00:24:493203 // Since we have proxy, should try to establish tunnel.
3204 MockWrite data_writes1[] = {
3205 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453206 "Host: www.google.com\r\n"
3207 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493208 };
3209
[email protected]77848d12008-11-14 00:00:223210 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493211 // connection. Usually a proxy would return 501 (not implemented),
3212 // or 200 (tunnel established).
3213 MockRead data_reads1[] = {
3214 MockRead("HTTP/1.1 404 Not Found\r\n"),
3215 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423216 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493217 };
3218
[email protected]31a2bfe2010-02-09 08:03:393219 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3220 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593221 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493222
3223 TestCompletionCallback callback1;
3224
[email protected]5a1d7ca2010-04-28 20:12:273225 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423226 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493227
3228 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423229 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493230
[email protected]1c773ea12009-04-28 19:58:423231 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083232 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493233
[email protected]b4404c02009-04-10 16:38:523234 // Empty the current queue. This is necessary because idle sockets are
3235 // added to the connection pool asynchronously with a PostTask.
3236 MessageLoop::current()->RunAllPending();
3237
[email protected]f4e426b2008-11-05 00:24:493238 // We now check to make sure the TCPClientSocket was not added back to
3239 // the pool.
[email protected]ab739042011-04-07 15:22:283240 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493241 trans.reset();
[email protected]b4404c02009-04-10 16:38:523242 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493243 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]ab739042011-04-07 15:22:283244 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493245}
[email protected]372d34a2008-11-05 21:30:513246
[email protected]1b157c02009-04-21 01:55:403247// Make sure that we recycle a socket after reading all of the response body.
3248TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423249 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403250 request.method = "GET";
3251 request.url = GURL("http://www.google.com/");
3252 request.load_flags = 0;
3253
[email protected]cb9bf6ca2011-01-28 13:15:273254 SessionDependencies session_deps;
3255 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3256
3257 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3258
[email protected]1b157c02009-04-21 01:55:403259 MockRead data_reads[] = {
3260 // A part of the response body is received with the response headers.
3261 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3262 // The rest of the response body is received in two parts.
3263 MockRead("lo"),
3264 MockRead(" world"),
3265 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423266 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403267 };
3268
[email protected]31a2bfe2010-02-09 08:03:393269 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593270 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403271
3272 TestCompletionCallback callback;
3273
[email protected]5a1d7ca2010-04-28 20:12:273274 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423275 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403276
3277 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423278 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403279
[email protected]1c773ea12009-04-28 19:58:423280 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:403281 EXPECT_TRUE(response != NULL);
3282
3283 EXPECT_TRUE(response->headers != NULL);
3284 std::string status_line = response->headers->GetStatusLine();
3285 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3286
[email protected]ab739042011-04-07 15:22:283287 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403288
3289 std::string response_data;
3290 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423291 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403292 EXPECT_EQ("hello world", response_data);
3293
3294 // Empty the current queue. This is necessary because idle sockets are
3295 // added to the connection pool asynchronously with a PostTask.
3296 MessageLoop::current()->RunAllPending();
3297
3298 // We now check to make sure the socket was added back to the pool.
[email protected]ab739042011-04-07 15:22:283299 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403300}
3301
[email protected]76a505b2010-08-25 06:23:003302// Make sure that we recycle a SSL socket after reading all of the response
3303// body.
3304TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3305 SessionDependencies session_deps;
3306 HttpRequestInfo request;
3307 request.method = "GET";
3308 request.url = GURL("https://www.google.com/");
3309 request.load_flags = 0;
3310
3311 MockWrite data_writes[] = {
3312 MockWrite("GET / HTTP/1.1\r\n"
3313 "Host: www.google.com\r\n"
3314 "Connection: keep-alive\r\n\r\n"),
3315 };
3316
3317 MockRead data_reads[] = {
3318 MockRead("HTTP/1.1 200 OK\r\n"),
3319 MockRead("Content-Length: 11\r\n\r\n"),
3320 MockRead("hello world"),
3321 MockRead(false, OK),
3322 };
3323
3324 SSLSocketDataProvider ssl(true, OK);
3325 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3326
3327 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3328 data_writes, arraysize(data_writes));
3329 session_deps.socket_factory.AddSocketDataProvider(&data);
3330
3331 TestCompletionCallback callback;
3332
3333 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3334 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3335
3336 int rv = trans->Start(&request, &callback, BoundNetLog());
3337
3338 EXPECT_EQ(ERR_IO_PENDING, rv);
3339 EXPECT_EQ(OK, callback.WaitForResult());
3340
3341 const HttpResponseInfo* response = trans->GetResponseInfo();
3342 ASSERT_TRUE(response != NULL);
3343 ASSERT_TRUE(response->headers != NULL);
3344 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3345
[email protected]ab739042011-04-07 15:22:283346 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003347
3348 std::string response_data;
3349 rv = ReadTransaction(trans.get(), &response_data);
3350 EXPECT_EQ(OK, rv);
3351 EXPECT_EQ("hello world", response_data);
3352
3353 // Empty the current queue. This is necessary because idle sockets are
3354 // added to the connection pool asynchronously with a PostTask.
3355 MessageLoop::current()->RunAllPending();
3356
3357 // We now check to make sure the socket was added back to the pool.
3358 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3359}
3360
3361// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3362// from the pool and make sure that we recover okay.
3363TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3364 SessionDependencies session_deps;
3365 HttpRequestInfo request;
3366 request.method = "GET";
3367 request.url = GURL("https://www.google.com/");
3368 request.load_flags = 0;
3369
3370 MockWrite data_writes[] = {
3371 MockWrite("GET / HTTP/1.1\r\n"
3372 "Host: www.google.com\r\n"
3373 "Connection: keep-alive\r\n\r\n"),
3374 MockWrite("GET / HTTP/1.1\r\n"
3375 "Host: www.google.com\r\n"
3376 "Connection: keep-alive\r\n\r\n"),
3377 };
3378
3379 MockRead data_reads[] = {
3380 MockRead("HTTP/1.1 200 OK\r\n"),
3381 MockRead("Content-Length: 11\r\n\r\n"),
3382 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3383 MockRead("hello world"),
3384 MockRead(true, 0, 0) // EOF
3385 };
3386
3387 SSLSocketDataProvider ssl(true, OK);
3388 SSLSocketDataProvider ssl2(true, OK);
3389 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3390 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3391
3392 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3393 data_writes, arraysize(data_writes));
3394 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3395 data_writes, arraysize(data_writes));
3396 session_deps.socket_factory.AddSocketDataProvider(&data);
3397 session_deps.socket_factory.AddSocketDataProvider(&data2);
3398
3399 TestCompletionCallback callback;
3400
3401 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3402 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3403
3404 int rv = trans->Start(&request, &callback, BoundNetLog());
3405
3406 EXPECT_EQ(ERR_IO_PENDING, rv);
3407 EXPECT_EQ(OK, callback.WaitForResult());
3408
3409 const HttpResponseInfo* response = trans->GetResponseInfo();
3410 ASSERT_TRUE(response != NULL);
3411 ASSERT_TRUE(response->headers != NULL);
3412 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3413
[email protected]ab739042011-04-07 15:22:283414 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003415
3416 std::string response_data;
3417 rv = ReadTransaction(trans.get(), &response_data);
3418 EXPECT_EQ(OK, rv);
3419 EXPECT_EQ("hello world", response_data);
3420
3421 // Empty the current queue. This is necessary because idle sockets are
3422 // added to the connection pool asynchronously with a PostTask.
3423 MessageLoop::current()->RunAllPending();
3424
3425 // We now check to make sure the socket was added back to the pool.
3426 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3427
3428 // Now start the second transaction, which should reuse the previous socket.
3429
3430 trans.reset(new HttpNetworkTransaction(session));
3431
3432 rv = trans->Start(&request, &callback, BoundNetLog());
3433
3434 EXPECT_EQ(ERR_IO_PENDING, rv);
3435 EXPECT_EQ(OK, callback.WaitForResult());
3436
3437 response = trans->GetResponseInfo();
3438 ASSERT_TRUE(response != NULL);
3439 ASSERT_TRUE(response->headers != NULL);
3440 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3441
[email protected]ab739042011-04-07 15:22:283442 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003443
3444 rv = ReadTransaction(trans.get(), &response_data);
3445 EXPECT_EQ(OK, rv);
3446 EXPECT_EQ("hello world", response_data);
3447
3448 // Empty the current queue. This is necessary because idle sockets are
3449 // added to the connection pool asynchronously with a PostTask.
3450 MessageLoop::current()->RunAllPending();
3451
3452 // We now check to make sure the socket was added back to the pool.
3453 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3454}
3455
[email protected]b4404c02009-04-10 16:38:523456// Make sure that we recycle a socket after a zero-length response.
3457// http://crbug.com/9880
3458TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423459 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523460 request.method = "GET";
3461 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3462 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3463 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3464 "rt=prt.2642,ol.2649,xjs.2951");
3465 request.load_flags = 0;
3466
[email protected]cb9bf6ca2011-01-28 13:15:273467 SessionDependencies session_deps;
3468 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3469
3470 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3471
[email protected]b4404c02009-04-10 16:38:523472 MockRead data_reads[] = {
3473 MockRead("HTTP/1.1 204 No Content\r\n"
3474 "Content-Length: 0\r\n"
3475 "Content-Type: text/html\r\n\r\n"),
3476 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423477 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523478 };
3479
[email protected]31a2bfe2010-02-09 08:03:393480 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593481 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523482
3483 TestCompletionCallback callback;
3484
[email protected]5a1d7ca2010-04-28 20:12:273485 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423486 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523487
3488 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423489 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523490
[email protected]1c773ea12009-04-28 19:58:423491 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523492 EXPECT_TRUE(response != NULL);
3493
3494 EXPECT_TRUE(response->headers != NULL);
3495 std::string status_line = response->headers->GetStatusLine();
3496 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3497
[email protected]ab739042011-04-07 15:22:283498 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523499
3500 std::string response_data;
3501 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423502 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523503 EXPECT_EQ("", response_data);
3504
3505 // Empty the current queue. This is necessary because idle sockets are
3506 // added to the connection pool asynchronously with a PostTask.
3507 MessageLoop::current()->RunAllPending();
3508
3509 // We now check to make sure the socket was added back to the pool.
[email protected]ab739042011-04-07 15:22:283510 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523511}
3512
[email protected]372d34a2008-11-05 21:30:513513TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423514 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513515 // Transaction 1: a GET request that succeeds. The socket is recycled
3516 // after use.
3517 request[0].method = "GET";
3518 request[0].url = GURL("http://www.google.com/");
3519 request[0].load_flags = 0;
3520 // Transaction 2: a POST request. Reuses the socket kept alive from
3521 // transaction 1. The first attempts fails when writing the POST data.
3522 // This causes the transaction to retry with a new socket. The second
3523 // attempt succeeds.
3524 request[1].method = "POST";
3525 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423526 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513527 request[1].upload_data->AppendBytes("foo", 3);
3528 request[1].load_flags = 0;
3529
[email protected]228ff742009-06-05 01:19:593530 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273531 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513532
3533 // The first socket is used for transaction 1 and the first attempt of
3534 // transaction 2.
3535
3536 // The response of transaction 1.
3537 MockRead data_reads1[] = {
3538 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3539 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423540 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513541 };
3542 // The mock write results of transaction 1 and the first attempt of
3543 // transaction 2.
3544 MockWrite data_writes1[] = {
3545 MockWrite(false, 64), // GET
3546 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423547 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513548 };
[email protected]31a2bfe2010-02-09 08:03:393549 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3550 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513551
3552 // The second socket is used for the second attempt of transaction 2.
3553
3554 // The response of transaction 2.
3555 MockRead data_reads2[] = {
3556 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3557 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423558 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513559 };
3560 // The mock write results of the second attempt of transaction 2.
3561 MockWrite data_writes2[] = {
3562 MockWrite(false, 93), // POST
3563 MockWrite(false, 3), // POST data
3564 };
[email protected]31a2bfe2010-02-09 08:03:393565 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3566 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513567
[email protected]5ecc992a42009-11-11 01:41:593568 session_deps.socket_factory.AddSocketDataProvider(&data1);
3569 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513570
3571 const char* kExpectedResponseData[] = {
3572 "hello world", "welcome"
3573 };
3574
3575 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423576 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433577 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513578
3579 TestCompletionCallback callback;
3580
[email protected]5a1d7ca2010-04-28 20:12:273581 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423582 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513583
3584 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423585 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513586
[email protected]1c773ea12009-04-28 19:58:423587 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513588 EXPECT_TRUE(response != NULL);
3589
3590 EXPECT_TRUE(response->headers != NULL);
3591 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3592
3593 std::string response_data;
3594 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423595 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513596 EXPECT_EQ(kExpectedResponseData[i], response_data);
3597 }
3598}
[email protected]f9ee6b52008-11-08 06:46:233599
3600// Test the request-challenge-retry sequence for basic auth when there is
3601// an identity in the URL. The request should be sent as normal, but when
3602// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323603TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423604 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233605 request.method = "GET";
3606 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293607 request.url = GURL("http://foo:b@[email protected]/");
3608
[email protected]cb9bf6ca2011-01-28 13:15:273609 SessionDependencies session_deps;
3610 scoped_ptr<HttpTransaction> trans(
3611 new HttpNetworkTransaction(CreateSession(&session_deps)));
3612
[email protected]a97cca42009-08-14 01:00:293613 // The password contains an escaped character -- for this test to pass it
3614 // will need to be unescaped by HttpNetworkTransaction.
3615 EXPECT_EQ("b%40r", request.url.password());
3616
[email protected]ea9dc9a2009-09-05 00:43:323617 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233618
3619 MockWrite data_writes1[] = {
3620 MockWrite("GET / HTTP/1.1\r\n"
3621 "Host: www.google.com\r\n"
3622 "Connection: keep-alive\r\n\r\n"),
3623 };
3624
3625 MockRead data_reads1[] = {
3626 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3627 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3628 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423629 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233630 };
3631
3632 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323633 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233634 MockWrite data_writes2[] = {
3635 MockWrite("GET / HTTP/1.1\r\n"
3636 "Host: www.google.com\r\n"
3637 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293638 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233639 };
3640
3641 MockRead data_reads2[] = {
3642 MockRead("HTTP/1.0 200 OK\r\n"),
3643 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423644 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233645 };
3646
[email protected]31a2bfe2010-02-09 08:03:393647 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3648 data_writes1, arraysize(data_writes1));
3649 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3650 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593651 session_deps.socket_factory.AddSocketDataProvider(&data1);
3652 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233653
3654 TestCompletionCallback callback1;
3655
[email protected]5a1d7ca2010-04-28 20:12:273656 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423657 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233658
3659 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423660 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233661
[email protected]0757e7702009-03-27 04:00:223662 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3663 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443664 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423665 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223666 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423667 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223668 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3669
[email protected]1c773ea12009-04-28 19:58:423670 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233671 EXPECT_FALSE(response == NULL);
3672
3673 // There is no challenge info, since the identity in URL worked.
3674 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3675
3676 EXPECT_EQ(100, response->headers->GetContentLength());
3677
3678 // Empty the current queue.
3679 MessageLoop::current()->RunAllPending();
3680}
3681
[email protected]ea9dc9a2009-09-05 00:43:323682// Test the request-challenge-retry sequence for basic auth when there is
3683// an incorrect identity in the URL. The identity from the URL should be used
3684// only once.
3685TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]ea9dc9a2009-09-05 00:43:323686 HttpRequestInfo request;
3687 request.method = "GET";
3688 // Note: the URL has a username:password in it. The password "baz" is
3689 // wrong (should be "bar").
3690 request.url = GURL("http://foo:[email protected]/");
3691
3692 request.load_flags = LOAD_NORMAL;
3693
[email protected]cb9bf6ca2011-01-28 13:15:273694 SessionDependencies session_deps;
3695 scoped_ptr<HttpTransaction> trans(
3696 new HttpNetworkTransaction(CreateSession(&session_deps)));
3697
[email protected]ea9dc9a2009-09-05 00:43:323698 MockWrite data_writes1[] = {
3699 MockWrite("GET / HTTP/1.1\r\n"
3700 "Host: www.google.com\r\n"
3701 "Connection: keep-alive\r\n\r\n"),
3702 };
3703
3704 MockRead data_reads1[] = {
3705 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3706 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3707 MockRead("Content-Length: 10\r\n\r\n"),
3708 MockRead(false, ERR_FAILED),
3709 };
3710
3711 // After the challenge above, the transaction will be restarted using the
3712 // identity from the url (foo, baz) to answer the challenge.
3713 MockWrite data_writes2[] = {
3714 MockWrite("GET / HTTP/1.1\r\n"
3715 "Host: www.google.com\r\n"
3716 "Connection: keep-alive\r\n"
3717 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3718 };
3719
3720 MockRead data_reads2[] = {
3721 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3722 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3723 MockRead("Content-Length: 10\r\n\r\n"),
3724 MockRead(false, ERR_FAILED),
3725 };
3726
3727 // After the challenge above, the transaction will be restarted using the
3728 // identity supplied by the user (foo, bar) to answer the challenge.
3729 MockWrite data_writes3[] = {
3730 MockWrite("GET / HTTP/1.1\r\n"
3731 "Host: www.google.com\r\n"
3732 "Connection: keep-alive\r\n"
3733 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3734 };
3735
3736 MockRead data_reads3[] = {
3737 MockRead("HTTP/1.0 200 OK\r\n"),
3738 MockRead("Content-Length: 100\r\n\r\n"),
3739 MockRead(false, OK),
3740 };
3741
[email protected]31a2bfe2010-02-09 08:03:393742 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3743 data_writes1, arraysize(data_writes1));
3744 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3745 data_writes2, arraysize(data_writes2));
3746 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3747 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593748 session_deps.socket_factory.AddSocketDataProvider(&data1);
3749 session_deps.socket_factory.AddSocketDataProvider(&data2);
3750 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323751
3752 TestCompletionCallback callback1;
3753
[email protected]5a1d7ca2010-04-28 20:12:273754 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323755 EXPECT_EQ(ERR_IO_PENDING, rv);
3756
3757 rv = callback1.WaitForResult();
3758 EXPECT_EQ(OK, rv);
3759
3760 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3761 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443762 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323763 EXPECT_EQ(ERR_IO_PENDING, rv);
3764 rv = callback2.WaitForResult();
3765 EXPECT_EQ(OK, rv);
3766 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3767
3768 const HttpResponseInfo* response = trans->GetResponseInfo();
3769 EXPECT_FALSE(response == NULL);
3770 // The password prompt info should have been set in response->auth_challenge.
3771 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3772
3773 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3774 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3775 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3776
3777 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443778 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323779 EXPECT_EQ(ERR_IO_PENDING, rv);
3780 rv = callback3.WaitForResult();
3781 EXPECT_EQ(OK, rv);
3782 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3783
3784 response = trans->GetResponseInfo();
3785 EXPECT_FALSE(response == NULL);
3786
3787 // There is no challenge info, since the identity worked.
3788 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3789
3790 EXPECT_EQ(100, response->headers->GetContentLength());
3791
3792 // Empty the current queue.
3793 MessageLoop::current()->RunAllPending();
3794}
3795
[email protected]f9ee6b52008-11-08 06:46:233796// Test that previously tried username/passwords for a realm get re-used.
3797TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593798 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273799 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233800
3801 // Transaction 1: authenticate (foo, bar) on MyRealm1
3802 {
[email protected]1c773ea12009-04-28 19:58:423803 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233804 request.method = "GET";
3805 request.url = GURL("http://www.google.com/x/y/z");
3806 request.load_flags = 0;
3807
[email protected]cb9bf6ca2011-01-28 13:15:273808 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3809
[email protected]f9ee6b52008-11-08 06:46:233810 MockWrite data_writes1[] = {
3811 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3812 "Host: www.google.com\r\n"
3813 "Connection: keep-alive\r\n\r\n"),
3814 };
3815
3816 MockRead data_reads1[] = {
3817 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3818 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3819 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423820 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233821 };
3822
3823 // Resend with authorization (username=foo, password=bar)
3824 MockWrite data_writes2[] = {
3825 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3826 "Host: www.google.com\r\n"
3827 "Connection: keep-alive\r\n"
3828 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3829 };
3830
3831 // Sever accepts the authorization.
3832 MockRead data_reads2[] = {
3833 MockRead("HTTP/1.0 200 OK\r\n"),
3834 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423835 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233836 };
3837
[email protected]31a2bfe2010-02-09 08:03:393838 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3839 data_writes1, arraysize(data_writes1));
3840 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3841 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593842 session_deps.socket_factory.AddSocketDataProvider(&data1);
3843 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233844
3845 TestCompletionCallback callback1;
3846
[email protected]5a1d7ca2010-04-28 20:12:273847 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423848 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233849
3850 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423851 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233852
[email protected]1c773ea12009-04-28 19:58:423853 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233854 EXPECT_FALSE(response == NULL);
3855
3856 // The password prompt info should have been set in
3857 // response->auth_challenge.
3858 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3859
[email protected]71e4573a2009-05-21 22:03:003860 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233861 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3862 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3863
3864 TestCompletionCallback callback2;
3865
[email protected]13c8a092010-07-29 06:15:443866 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423867 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233868
3869 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423870 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233871
3872 response = trans->GetResponseInfo();
3873 EXPECT_FALSE(response == NULL);
3874 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3875 EXPECT_EQ(100, response->headers->GetContentLength());
3876 }
3877
3878 // ------------------------------------------------------------------------
3879
3880 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3881 {
[email protected]1c773ea12009-04-28 19:58:423882 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233883 request.method = "GET";
3884 // Note that Transaction 1 was at /x/y/z, so this is in the same
3885 // protection space as MyRealm1.
3886 request.url = GURL("http://www.google.com/x/y/a/b");
3887 request.load_flags = 0;
3888
[email protected]cb9bf6ca2011-01-28 13:15:273889 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3890
[email protected]f9ee6b52008-11-08 06:46:233891 MockWrite data_writes1[] = {
3892 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3893 "Host: www.google.com\r\n"
3894 "Connection: keep-alive\r\n"
3895 // Send preemptive authorization for MyRealm1
3896 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3897 };
3898
3899 // The server didn't like the preemptive authorization, and
3900 // challenges us for a different realm (MyRealm2).
3901 MockRead data_reads1[] = {
3902 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3903 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3904 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423905 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233906 };
3907
3908 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3909 MockWrite data_writes2[] = {
3910 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3911 "Host: www.google.com\r\n"
3912 "Connection: keep-alive\r\n"
3913 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3914 };
3915
3916 // Sever accepts the authorization.
3917 MockRead data_reads2[] = {
3918 MockRead("HTTP/1.0 200 OK\r\n"),
3919 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423920 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233921 };
3922
[email protected]31a2bfe2010-02-09 08:03:393923 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3924 data_writes1, arraysize(data_writes1));
3925 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3926 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593927 session_deps.socket_factory.AddSocketDataProvider(&data1);
3928 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233929
3930 TestCompletionCallback callback1;
3931
[email protected]5a1d7ca2010-04-28 20:12:273932 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423933 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233934
3935 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423936 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233937
[email protected]1c773ea12009-04-28 19:58:423938 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233939 EXPECT_FALSE(response == NULL);
3940
3941 // The password prompt info should have been set in
3942 // response->auth_challenge.
3943 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3944
[email protected]71e4573a2009-05-21 22:03:003945 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233946 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3947 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3948
3949 TestCompletionCallback callback2;
3950
[email protected]13c8a092010-07-29 06:15:443951 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423952 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233953
3954 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423955 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233956
3957 response = trans->GetResponseInfo();
3958 EXPECT_FALSE(response == NULL);
3959 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3960 EXPECT_EQ(100, response->headers->GetContentLength());
3961 }
3962
3963 // ------------------------------------------------------------------------
3964
3965 // Transaction 3: Resend a request in MyRealm's protection space --
3966 // succeed with preemptive authorization.
3967 {
[email protected]1c773ea12009-04-28 19:58:423968 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233969 request.method = "GET";
3970 request.url = GURL("http://www.google.com/x/y/z2");
3971 request.load_flags = 0;
3972
[email protected]cb9bf6ca2011-01-28 13:15:273973 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3974
[email protected]f9ee6b52008-11-08 06:46:233975 MockWrite data_writes1[] = {
3976 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3977 "Host: www.google.com\r\n"
3978 "Connection: keep-alive\r\n"
3979 // The authorization for MyRealm1 gets sent preemptively
3980 // (since the url is in the same protection space)
3981 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3982 };
3983
3984 // Sever accepts the preemptive authorization
3985 MockRead data_reads1[] = {
3986 MockRead("HTTP/1.0 200 OK\r\n"),
3987 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423988 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233989 };
3990
[email protected]31a2bfe2010-02-09 08:03:393991 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3992 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593993 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233994
3995 TestCompletionCallback callback1;
3996
[email protected]5a1d7ca2010-04-28 20:12:273997 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423998 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233999
4000 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424001 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234002
[email protected]1c773ea12009-04-28 19:58:424003 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234004 EXPECT_FALSE(response == NULL);
4005
4006 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4007 EXPECT_EQ(100, response->headers->GetContentLength());
4008 }
4009
4010 // ------------------------------------------------------------------------
4011
4012 // Transaction 4: request another URL in MyRealm (however the
4013 // url is not known to belong to the protection space, so no pre-auth).
4014 {
[email protected]1c773ea12009-04-28 19:58:424015 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234016 request.method = "GET";
4017 request.url = GURL("http://www.google.com/x/1");
4018 request.load_flags = 0;
4019
[email protected]cb9bf6ca2011-01-28 13:15:274020 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4021
[email protected]f9ee6b52008-11-08 06:46:234022 MockWrite data_writes1[] = {
4023 MockWrite("GET /x/1 HTTP/1.1\r\n"
4024 "Host: www.google.com\r\n"
4025 "Connection: keep-alive\r\n\r\n"),
4026 };
4027
4028 MockRead data_reads1[] = {
4029 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4030 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4031 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424032 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234033 };
4034
4035 // Resend with authorization from MyRealm's cache.
4036 MockWrite data_writes2[] = {
4037 MockWrite("GET /x/1 HTTP/1.1\r\n"
4038 "Host: www.google.com\r\n"
4039 "Connection: keep-alive\r\n"
4040 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4041 };
4042
4043 // Sever accepts the authorization.
4044 MockRead data_reads2[] = {
4045 MockRead("HTTP/1.0 200 OK\r\n"),
4046 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424047 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234048 };
4049
[email protected]31a2bfe2010-02-09 08:03:394050 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4051 data_writes1, arraysize(data_writes1));
4052 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4053 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594054 session_deps.socket_factory.AddSocketDataProvider(&data1);
4055 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:234056
4057 TestCompletionCallback callback1;
4058
[email protected]5a1d7ca2010-04-28 20:12:274059 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424060 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234061
4062 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424063 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234064
[email protected]0757e7702009-03-27 04:00:224065 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4066 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444067 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424068 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224069 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424070 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224071 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4072
[email protected]1c773ea12009-04-28 19:58:424073 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234074 EXPECT_FALSE(response == NULL);
4075 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4076 EXPECT_EQ(100, response->headers->GetContentLength());
4077 }
4078
4079 // ------------------------------------------------------------------------
4080
4081 // Transaction 5: request a URL in MyRealm, but the server rejects the
4082 // cached identity. Should invalidate and re-prompt.
4083 {
[email protected]1c773ea12009-04-28 19:58:424084 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234085 request.method = "GET";
4086 request.url = GURL("http://www.google.com/p/q/t");
4087 request.load_flags = 0;
4088
[email protected]cb9bf6ca2011-01-28 13:15:274089 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4090
[email protected]f9ee6b52008-11-08 06:46:234091 MockWrite data_writes1[] = {
4092 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4093 "Host: www.google.com\r\n"
4094 "Connection: keep-alive\r\n\r\n"),
4095 };
4096
4097 MockRead data_reads1[] = {
4098 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4099 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4100 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424101 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234102 };
4103
4104 // Resend with authorization from cache for MyRealm.
4105 MockWrite data_writes2[] = {
4106 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4107 "Host: www.google.com\r\n"
4108 "Connection: keep-alive\r\n"
4109 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4110 };
4111
4112 // Sever rejects the authorization.
4113 MockRead data_reads2[] = {
4114 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4115 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4116 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424117 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234118 };
4119
4120 // At this point we should prompt for new credentials for MyRealm.
4121 // Restart with username=foo3, password=foo4.
4122 MockWrite data_writes3[] = {
4123 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4124 "Host: www.google.com\r\n"
4125 "Connection: keep-alive\r\n"
4126 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4127 };
4128
4129 // Sever accepts the authorization.
4130 MockRead data_reads3[] = {
4131 MockRead("HTTP/1.0 200 OK\r\n"),
4132 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424133 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234134 };
4135
[email protected]31a2bfe2010-02-09 08:03:394136 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4137 data_writes1, arraysize(data_writes1));
4138 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4139 data_writes2, arraysize(data_writes2));
4140 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4141 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594142 session_deps.socket_factory.AddSocketDataProvider(&data1);
4143 session_deps.socket_factory.AddSocketDataProvider(&data2);
4144 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234145
4146 TestCompletionCallback callback1;
4147
[email protected]5a1d7ca2010-04-28 20:12:274148 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424149 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234150
4151 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424152 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234153
[email protected]0757e7702009-03-27 04:00:224154 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4155 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444156 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424157 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224158 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424159 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224160 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4161
[email protected]1c773ea12009-04-28 19:58:424162 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234163 EXPECT_FALSE(response == NULL);
4164
4165 // The password prompt info should have been set in
4166 // response->auth_challenge.
4167 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4168
[email protected]71e4573a2009-05-21 22:03:004169 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:234170 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4171 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4172
[email protected]0757e7702009-03-27 04:00:224173 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234174
[email protected]13c8a092010-07-29 06:15:444175 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:424176 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234177
[email protected]0757e7702009-03-27 04:00:224178 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424179 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234180
4181 response = trans->GetResponseInfo();
4182 EXPECT_FALSE(response == NULL);
4183 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4184 EXPECT_EQ(100, response->headers->GetContentLength());
4185 }
4186}
[email protected]89ceba9a2009-03-21 03:46:064187
[email protected]3c32c5f2010-05-18 15:18:124188// Tests that nonce count increments when multiple auth attempts
4189// are started with the same nonce.
4190TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4191 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444192 HttpAuthHandlerDigest::Factory* digest_factory =
4193 new HttpAuthHandlerDigest::Factory();
4194 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4195 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4196 digest_factory->set_nonce_generator(nonce_generator);
4197 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274198 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124199
4200 // Transaction 1: authenticate (foo, bar) on MyRealm1
4201 {
[email protected]3c32c5f2010-05-18 15:18:124202 HttpRequestInfo request;
4203 request.method = "GET";
4204 request.url = GURL("http://www.google.com/x/y/z");
4205 request.load_flags = 0;
4206
[email protected]cb9bf6ca2011-01-28 13:15:274207 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4208
[email protected]3c32c5f2010-05-18 15:18:124209 MockWrite data_writes1[] = {
4210 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4211 "Host: www.google.com\r\n"
4212 "Connection: keep-alive\r\n\r\n"),
4213 };
4214
4215 MockRead data_reads1[] = {
4216 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4217 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4218 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4219 MockRead(false, OK),
4220 };
4221
4222 // Resend with authorization (username=foo, password=bar)
4223 MockWrite data_writes2[] = {
4224 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4225 "Host: www.google.com\r\n"
4226 "Connection: keep-alive\r\n"
4227 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4228 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4229 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4230 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4231 };
4232
4233 // Sever accepts the authorization.
4234 MockRead data_reads2[] = {
4235 MockRead("HTTP/1.0 200 OK\r\n"),
4236 MockRead(false, OK),
4237 };
4238
4239 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4240 data_writes1, arraysize(data_writes1));
4241 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4242 data_writes2, arraysize(data_writes2));
4243 session_deps.socket_factory.AddSocketDataProvider(&data1);
4244 session_deps.socket_factory.AddSocketDataProvider(&data2);
4245
4246 TestCompletionCallback callback1;
4247
4248 int rv = trans->Start(&request, &callback1, BoundNetLog());
4249 EXPECT_EQ(ERR_IO_PENDING, rv);
4250
4251 rv = callback1.WaitForResult();
4252 EXPECT_EQ(OK, rv);
4253
4254 const HttpResponseInfo* response = trans->GetResponseInfo();
4255 ASSERT_FALSE(response == NULL);
4256
4257 // The password prompt info should have been set in
4258 // response->auth_challenge.
4259 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4260
4261 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4262 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
4263 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
4264
4265 TestCompletionCallback callback2;
4266
[email protected]13c8a092010-07-29 06:15:444267 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:124268 EXPECT_EQ(ERR_IO_PENDING, rv);
4269
4270 rv = callback2.WaitForResult();
4271 EXPECT_EQ(OK, rv);
4272
4273 response = trans->GetResponseInfo();
4274 ASSERT_FALSE(response == NULL);
4275 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4276 }
4277
4278 // ------------------------------------------------------------------------
4279
4280 // Transaction 2: Request another resource in digestive's protection space.
4281 // This will preemptively add an Authorization header which should have an
4282 // "nc" value of 2 (as compared to 1 in the first use.
4283 {
[email protected]3c32c5f2010-05-18 15:18:124284 HttpRequestInfo request;
4285 request.method = "GET";
4286 // Note that Transaction 1 was at /x/y/z, so this is in the same
4287 // protection space as digest.
4288 request.url = GURL("http://www.google.com/x/y/a/b");
4289 request.load_flags = 0;
4290
[email protected]cb9bf6ca2011-01-28 13:15:274291 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4292
[email protected]3c32c5f2010-05-18 15:18:124293 MockWrite data_writes1[] = {
4294 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4295 "Host: www.google.com\r\n"
4296 "Connection: keep-alive\r\n"
4297 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4298 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4299 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4300 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4301 };
4302
4303 // Sever accepts the authorization.
4304 MockRead data_reads1[] = {
4305 MockRead("HTTP/1.0 200 OK\r\n"),
4306 MockRead("Content-Length: 100\r\n\r\n"),
4307 MockRead(false, OK),
4308 };
4309
4310 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4311 data_writes1, arraysize(data_writes1));
4312 session_deps.socket_factory.AddSocketDataProvider(&data1);
4313
4314 TestCompletionCallback callback1;
4315
4316 int rv = trans->Start(&request, &callback1, BoundNetLog());
4317 EXPECT_EQ(ERR_IO_PENDING, rv);
4318
4319 rv = callback1.WaitForResult();
4320 EXPECT_EQ(OK, rv);
4321
4322 const HttpResponseInfo* response = trans->GetResponseInfo();
4323 ASSERT_FALSE(response == NULL);
4324 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4325 }
4326}
4327
[email protected]89ceba9a2009-03-21 03:46:064328// Test the ResetStateForRestart() private method.
4329TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4330 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594331 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404332 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434333 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064334
4335 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064336 trans->read_buf_ = new IOBuffer(15);
4337 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204338 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064339
4340 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144341 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574342 response->auth_challenge = new AuthChallengeInfo();
4343 response->ssl_info.cert_status = -15;
4344 response->response_time = base::Time::Now();
4345 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064346
4347 { // Setup state for response_.vary_data
4348 HttpRequestInfo request;
4349 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4350 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274351 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434352 request.extra_headers.SetHeader("Foo", "1");
4353 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574354 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064355 }
4356
4357 // Cause the above state to be reset.
4358 trans->ResetStateForRestart();
4359
4360 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074361 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064362 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204363 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574364 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4365 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044366 EXPECT_FALSE(response->was_cached);
[email protected]0877e3d2009-10-17 22:29:574367 EXPECT_EQ(0, response->ssl_info.cert_status);
4368 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064369}
4370
[email protected]bacff652009-03-31 17:50:334371// Test HTTPS connections to a site with a bad certificate
4372TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334373 HttpRequestInfo request;
4374 request.method = "GET";
4375 request.url = GURL("https://www.google.com/");
4376 request.load_flags = 0;
4377
[email protected]cb9bf6ca2011-01-28 13:15:274378 SessionDependencies session_deps;
4379 scoped_ptr<HttpTransaction> trans(
4380 new HttpNetworkTransaction(CreateSession(&session_deps)));
4381
[email protected]bacff652009-03-31 17:50:334382 MockWrite data_writes[] = {
4383 MockWrite("GET / HTTP/1.1\r\n"
4384 "Host: www.google.com\r\n"
4385 "Connection: keep-alive\r\n\r\n"),
4386 };
4387
4388 MockRead data_reads[] = {
4389 MockRead("HTTP/1.0 200 OK\r\n"),
4390 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4391 MockRead("Content-Length: 100\r\n\r\n"),
4392 MockRead(false, OK),
4393 };
4394
[email protected]5ecc992a42009-11-11 01:41:594395 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394396 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4397 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594398 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4399 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334400
[email protected]5ecc992a42009-11-11 01:41:594401 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4402 session_deps.socket_factory.AddSocketDataProvider(&data);
4403 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4404 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334405
4406 TestCompletionCallback callback;
4407
[email protected]5a1d7ca2010-04-28 20:12:274408 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334409 EXPECT_EQ(ERR_IO_PENDING, rv);
4410
4411 rv = callback.WaitForResult();
4412 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4413
4414 rv = trans->RestartIgnoringLastError(&callback);
4415 EXPECT_EQ(ERR_IO_PENDING, rv);
4416
4417 rv = callback.WaitForResult();
4418 EXPECT_EQ(OK, rv);
4419
4420 const HttpResponseInfo* response = trans->GetResponseInfo();
4421
4422 EXPECT_FALSE(response == NULL);
4423 EXPECT_EQ(100, response->headers->GetContentLength());
4424}
4425
4426// Test HTTPS connections to a site with a bad certificate, going through a
4427// proxy
4428TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004429 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334430
4431 HttpRequestInfo request;
4432 request.method = "GET";
4433 request.url = GURL("https://www.google.com/");
4434 request.load_flags = 0;
4435
4436 MockWrite proxy_writes[] = {
4437 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454438 "Host: www.google.com\r\n"
4439 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334440 };
4441
4442 MockRead proxy_reads[] = {
4443 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424444 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334445 };
4446
4447 MockWrite data_writes[] = {
4448 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454449 "Host: www.google.com\r\n"
4450 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334451 MockWrite("GET / HTTP/1.1\r\n"
4452 "Host: www.google.com\r\n"
4453 "Connection: keep-alive\r\n\r\n"),
4454 };
4455
4456 MockRead data_reads[] = {
4457 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4458 MockRead("HTTP/1.0 200 OK\r\n"),
4459 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4460 MockRead("Content-Length: 100\r\n\r\n"),
4461 MockRead(false, OK),
4462 };
4463
[email protected]31a2bfe2010-02-09 08:03:394464 StaticSocketDataProvider ssl_bad_certificate(
4465 proxy_reads, arraysize(proxy_reads),
4466 proxy_writes, arraysize(proxy_writes));
4467 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4468 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594469 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4470 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334471
[email protected]5ecc992a42009-11-11 01:41:594472 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4473 session_deps.socket_factory.AddSocketDataProvider(&data);
4474 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4475 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334476
4477 TestCompletionCallback callback;
4478
4479 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594480 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334481
[email protected]d207a5f2009-06-04 05:28:404482 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434483 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334484
[email protected]5a1d7ca2010-04-28 20:12:274485 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334486 EXPECT_EQ(ERR_IO_PENDING, rv);
4487
4488 rv = callback.WaitForResult();
4489 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4490
4491 rv = trans->RestartIgnoringLastError(&callback);
4492 EXPECT_EQ(ERR_IO_PENDING, rv);
4493
4494 rv = callback.WaitForResult();
4495 EXPECT_EQ(OK, rv);
4496
4497 const HttpResponseInfo* response = trans->GetResponseInfo();
4498
4499 EXPECT_FALSE(response == NULL);
4500 EXPECT_EQ(100, response->headers->GetContentLength());
4501 }
4502}
4503
[email protected]2df19bb2010-08-25 20:13:464504
4505// Test HTTPS connections to a site, going through an HTTPS proxy
4506TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004507 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464508
4509 HttpRequestInfo request;
4510 request.method = "GET";
4511 request.url = GURL("https://www.google.com/");
4512 request.load_flags = 0;
4513
4514 MockWrite data_writes[] = {
4515 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4516 "Host: www.google.com\r\n"
4517 "Proxy-Connection: keep-alive\r\n\r\n"),
4518 MockWrite("GET / HTTP/1.1\r\n"
4519 "Host: www.google.com\r\n"
4520 "Connection: keep-alive\r\n\r\n"),
4521 };
4522
4523 MockRead data_reads[] = {
4524 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4525 MockRead("HTTP/1.1 200 OK\r\n"),
4526 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4527 MockRead("Content-Length: 100\r\n\r\n"),
4528 MockRead(false, OK),
4529 };
4530
4531 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4532 data_writes, arraysize(data_writes));
4533 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4534 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4535
4536 session_deps.socket_factory.AddSocketDataProvider(&data);
4537 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4538 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4539
4540 TestCompletionCallback callback;
4541
4542 scoped_ptr<HttpTransaction> trans(
4543 new HttpNetworkTransaction(CreateSession(&session_deps)));
4544
4545 int rv = trans->Start(&request, &callback, BoundNetLog());
4546 EXPECT_EQ(ERR_IO_PENDING, rv);
4547
4548 rv = callback.WaitForResult();
4549 EXPECT_EQ(OK, rv);
4550 const HttpResponseInfo* response = trans->GetResponseInfo();
4551
4552 ASSERT_FALSE(response == NULL);
4553
4554 EXPECT_TRUE(response->headers->IsKeepAlive());
4555 EXPECT_EQ(200, response->headers->response_code());
4556 EXPECT_EQ(100, response->headers->GetContentLength());
4557 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4558}
4559
[email protected]511f6f52010-12-17 03:58:294560// Test an HTTPS Proxy's ability to redirect a CONNECT request
4561TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4562 SessionDependencies session_deps(
4563 ProxyService::CreateFixed("https://proxy:70"));
4564
4565 HttpRequestInfo request;
4566 request.method = "GET";
4567 request.url = GURL("https://www.google.com/");
4568 request.load_flags = 0;
4569
4570 MockWrite data_writes[] = {
4571 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4572 "Host: www.google.com\r\n"
4573 "Proxy-Connection: keep-alive\r\n\r\n"),
4574 };
4575
4576 MockRead data_reads[] = {
4577 MockRead("HTTP/1.1 302 Redirect\r\n"),
4578 MockRead("Location: http://login.example.com/\r\n"),
4579 MockRead("Content-Length: 0\r\n\r\n"),
4580 MockRead(false, OK),
4581 };
4582
4583 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4584 data_writes, arraysize(data_writes));
4585 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4586
4587 session_deps.socket_factory.AddSocketDataProvider(&data);
4588 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4589
4590 TestCompletionCallback callback;
4591
4592 scoped_ptr<HttpTransaction> trans(
4593 new HttpNetworkTransaction(CreateSession(&session_deps)));
4594
4595 int rv = trans->Start(&request, &callback, BoundNetLog());
4596 EXPECT_EQ(ERR_IO_PENDING, rv);
4597
4598 rv = callback.WaitForResult();
4599 EXPECT_EQ(OK, rv);
4600 const HttpResponseInfo* response = trans->GetResponseInfo();
4601
4602 ASSERT_FALSE(response == NULL);
4603
4604 EXPECT_EQ(302, response->headers->response_code());
4605 std::string url;
4606 EXPECT_TRUE(response->headers->IsRedirect(&url));
4607 EXPECT_EQ("http://login.example.com/", url);
4608}
4609
4610// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4611TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4612 SessionDependencies session_deps(
4613 ProxyService::CreateFixed("https://proxy:70"));
4614
4615 HttpRequestInfo request;
4616 request.method = "GET";
4617 request.url = GURL("https://www.google.com/");
4618 request.load_flags = 0;
4619
4620 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4621 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4622 MockWrite data_writes[] = {
4623 CreateMockWrite(*conn.get(), 0, false),
4624 };
4625
4626 static const char* const kExtraHeaders[] = {
4627 "location",
4628 "http://login.example.com/",
4629 };
4630 scoped_ptr<spdy::SpdyFrame> resp(
4631 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4632 arraysize(kExtraHeaders)/2, 1));
4633 MockRead data_reads[] = {
4634 CreateMockRead(*resp.get(), 1, false),
4635 MockRead(true, 0, 2), // EOF
4636 };
4637
4638 scoped_refptr<DelayedSocketData> data(
4639 new DelayedSocketData(
4640 1, // wait for one write to finish before reading.
4641 data_reads, arraysize(data_reads),
4642 data_writes, arraysize(data_writes)));
4643 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4644 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4645 proxy_ssl.next_proto = "spdy/2";
4646 proxy_ssl.was_npn_negotiated = true;
4647
4648 session_deps.socket_factory.AddSocketDataProvider(data.get());
4649 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4650
4651 TestCompletionCallback callback;
4652
4653 scoped_ptr<HttpTransaction> trans(
4654 new HttpNetworkTransaction(CreateSession(&session_deps)));
4655
4656 int rv = trans->Start(&request, &callback, BoundNetLog());
4657 EXPECT_EQ(ERR_IO_PENDING, rv);
4658
4659 rv = callback.WaitForResult();
4660 EXPECT_EQ(OK, rv);
4661 const HttpResponseInfo* response = trans->GetResponseInfo();
4662
4663 ASSERT_FALSE(response == NULL);
4664
4665 EXPECT_EQ(302, response->headers->response_code());
4666 std::string url;
4667 EXPECT_TRUE(response->headers->IsRedirect(&url));
4668 EXPECT_EQ("http://login.example.com/", url);
4669}
4670
4671// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4672TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4673 SessionDependencies session_deps(
4674 ProxyService::CreateFixed("https://proxy:70"));
4675
4676 HttpRequestInfo request;
4677 request.method = "GET";
4678 request.url = GURL("https://www.google.com/");
4679 request.load_flags = 0;
4680
4681 MockWrite data_writes[] = {
4682 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4683 "Host: www.google.com\r\n"
4684 "Proxy-Connection: keep-alive\r\n\r\n"),
4685 };
4686
4687 MockRead data_reads[] = {
4688 MockRead("HTTP/1.1 404 Not Found\r\n"),
4689 MockRead("Content-Length: 23\r\n\r\n"),
4690 MockRead("The host does not exist"),
4691 MockRead(false, OK),
4692 };
4693
4694 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4695 data_writes, arraysize(data_writes));
4696 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4697
4698 session_deps.socket_factory.AddSocketDataProvider(&data);
4699 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4700
4701 TestCompletionCallback callback;
4702
4703 scoped_ptr<HttpTransaction> trans(
4704 new HttpNetworkTransaction(CreateSession(&session_deps)));
4705
4706 int rv = trans->Start(&request, &callback, BoundNetLog());
4707 EXPECT_EQ(ERR_IO_PENDING, rv);
4708
4709 rv = callback.WaitForResult();
4710 EXPECT_EQ(OK, rv);
4711 const HttpResponseInfo* response = trans->GetResponseInfo();
4712
4713 ASSERT_FALSE(response == NULL);
4714
4715 EXPECT_EQ(404, response->headers->response_code());
4716 EXPECT_EQ(23, response->headers->GetContentLength());
4717 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4718 EXPECT_FALSE(response->ssl_info.is_valid());
4719
4720 std::string response_data;
4721 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4722 EXPECT_EQ("The host does not exist", response_data);
4723}
4724
4725// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4726// request
4727TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4728 SessionDependencies session_deps(
4729 ProxyService::CreateFixed("https://proxy:70"));
4730
4731 HttpRequestInfo request;
4732 request.method = "GET";
4733 request.url = GURL("https://www.google.com/");
4734 request.load_flags = 0;
4735
4736 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4737 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4738 MockWrite data_writes[] = {
4739 CreateMockWrite(*conn.get(), 0, false),
4740 };
4741
4742 static const char* const kExtraHeaders[] = {
4743 "location",
4744 "http://login.example.com/",
4745 };
4746 scoped_ptr<spdy::SpdyFrame> resp(
4747 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4748 arraysize(kExtraHeaders)/2, 1));
4749 scoped_ptr<spdy::SpdyFrame> body(
4750 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4751 MockRead data_reads[] = {
4752 CreateMockRead(*resp.get(), 1, false),
4753 CreateMockRead(*body.get(), 2, false),
4754 MockRead(true, 0, 3), // EOF
4755 };
4756
4757 scoped_refptr<DelayedSocketData> data(
4758 new DelayedSocketData(
4759 1, // wait for one write to finish before reading.
4760 data_reads, arraysize(data_reads),
4761 data_writes, arraysize(data_writes)));
4762 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4763 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4764 proxy_ssl.next_proto = "spdy/2";
4765 proxy_ssl.was_npn_negotiated = true;
4766
4767 session_deps.socket_factory.AddSocketDataProvider(data.get());
4768 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4769
4770 TestCompletionCallback callback;
4771
4772 scoped_ptr<HttpTransaction> trans(
4773 new HttpNetworkTransaction(CreateSession(&session_deps)));
4774
4775 int rv = trans->Start(&request, &callback, BoundNetLog());
4776 EXPECT_EQ(ERR_IO_PENDING, rv);
4777
4778 rv = callback.WaitForResult();
4779 EXPECT_EQ(OK, rv);
4780 const HttpResponseInfo* response = trans->GetResponseInfo();
4781
4782 ASSERT_FALSE(response == NULL);
4783
4784 EXPECT_EQ(404, response->headers->response_code());
4785 EXPECT_FALSE(response->ssl_info.is_valid());
4786
4787 std::string response_data;
4788 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4789 EXPECT_EQ("The host does not exist", response_data);
4790}
4791
[email protected]2df19bb2010-08-25 20:13:464792// Test HTTPS connections to a site with a bad certificate, going through an
4793// HTTPS proxy
4794TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004795 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464796
4797 HttpRequestInfo request;
4798 request.method = "GET";
4799 request.url = GURL("https://www.google.com/");
4800 request.load_flags = 0;
4801
4802 // Attempt to fetch the URL from a server with a bad cert
4803 MockWrite bad_cert_writes[] = {
4804 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4805 "Host: www.google.com\r\n"
4806 "Proxy-Connection: keep-alive\r\n\r\n"),
4807 };
4808
4809 MockRead bad_cert_reads[] = {
4810 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4811 MockRead(false, OK)
4812 };
4813
4814 // Attempt to fetch the URL with a good cert
4815 MockWrite good_data_writes[] = {
4816 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4817 "Host: www.google.com\r\n"
4818 "Proxy-Connection: keep-alive\r\n\r\n"),
4819 MockWrite("GET / HTTP/1.1\r\n"
4820 "Host: www.google.com\r\n"
4821 "Connection: keep-alive\r\n\r\n"),
4822 };
4823
4824 MockRead good_cert_reads[] = {
4825 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4826 MockRead("HTTP/1.0 200 OK\r\n"),
4827 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4828 MockRead("Content-Length: 100\r\n\r\n"),
4829 MockRead(false, OK),
4830 };
4831
4832 StaticSocketDataProvider ssl_bad_certificate(
4833 bad_cert_reads, arraysize(bad_cert_reads),
4834 bad_cert_writes, arraysize(bad_cert_writes));
4835 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4836 good_data_writes, arraysize(good_data_writes));
4837 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4838 SSLSocketDataProvider ssl(true, OK);
4839
4840 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4841 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4842 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4843 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4844
4845 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4846 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4847 session_deps.socket_factory.AddSocketDataProvider(&data);
4848 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4849
4850 TestCompletionCallback callback;
4851
4852 scoped_ptr<HttpTransaction> trans(
4853 new HttpNetworkTransaction(CreateSession(&session_deps)));
4854
4855 int rv = trans->Start(&request, &callback, BoundNetLog());
4856 EXPECT_EQ(ERR_IO_PENDING, rv);
4857
4858 rv = callback.WaitForResult();
4859 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4860
4861 rv = trans->RestartIgnoringLastError(&callback);
4862 EXPECT_EQ(ERR_IO_PENDING, rv);
4863
4864 rv = callback.WaitForResult();
4865 EXPECT_EQ(OK, rv);
4866
4867 const HttpResponseInfo* response = trans->GetResponseInfo();
4868
4869 EXPECT_FALSE(response == NULL);
4870 EXPECT_EQ(100, response->headers->GetContentLength());
4871}
4872
[email protected]1c773ea12009-04-28 19:58:424873TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424874 HttpRequestInfo request;
4875 request.method = "GET";
4876 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434877 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4878 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424879
[email protected]cb9bf6ca2011-01-28 13:15:274880 SessionDependencies session_deps;
4881 scoped_ptr<HttpTransaction> trans(
4882 new HttpNetworkTransaction(CreateSession(&session_deps)));
4883
[email protected]1c773ea12009-04-28 19:58:424884 MockWrite data_writes[] = {
4885 MockWrite("GET / HTTP/1.1\r\n"
4886 "Host: www.google.com\r\n"
4887 "Connection: keep-alive\r\n"
4888 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4889 };
4890
4891 // Lastly, the server responds with the actual content.
4892 MockRead data_reads[] = {
4893 MockRead("HTTP/1.0 200 OK\r\n"),
4894 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4895 MockRead("Content-Length: 100\r\n\r\n"),
4896 MockRead(false, OK),
4897 };
4898
[email protected]31a2bfe2010-02-09 08:03:394899 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4900 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594901 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424902
4903 TestCompletionCallback callback;
4904
[email protected]5a1d7ca2010-04-28 20:12:274905 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424906 EXPECT_EQ(ERR_IO_PENDING, rv);
4907
4908 rv = callback.WaitForResult();
4909 EXPECT_EQ(OK, rv);
4910}
4911
[email protected]da81f132010-08-18 23:39:294912TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:294913 HttpRequestInfo request;
4914 request.method = "GET";
4915 request.url = GURL("https://www.google.com/");
4916 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4917 "Chromium Ultra Awesome X Edition");
4918
[email protected]cb9bf6ca2011-01-28 13:15:274919 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4920 scoped_ptr<HttpTransaction> trans(
4921 new HttpNetworkTransaction(CreateSession(&session_deps)));
4922
[email protected]da81f132010-08-18 23:39:294923 MockWrite data_writes[] = {
4924 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4925 "Host: www.google.com\r\n"
4926 "Proxy-Connection: keep-alive\r\n"
4927 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4928 };
4929 MockRead data_reads[] = {
4930 // Return an error, so the transaction stops here (this test isn't
4931 // interested in the rest).
4932 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4933 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4934 MockRead("Proxy-Connection: close\r\n\r\n"),
4935 };
4936
4937 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4938 data_writes, arraysize(data_writes));
4939 session_deps.socket_factory.AddSocketDataProvider(&data);
4940
4941 TestCompletionCallback callback;
4942
4943 int rv = trans->Start(&request, &callback, BoundNetLog());
4944 EXPECT_EQ(ERR_IO_PENDING, rv);
4945
4946 rv = callback.WaitForResult();
4947 EXPECT_EQ(OK, rv);
4948}
4949
[email protected]1c773ea12009-04-28 19:58:424950TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:424951 HttpRequestInfo request;
4952 request.method = "GET";
4953 request.url = GURL("http://www.google.com/");
4954 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:164955 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
4956 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:424957
[email protected]cb9bf6ca2011-01-28 13:15:274958 SessionDependencies session_deps;
4959 scoped_ptr<HttpTransaction> trans(
4960 new HttpNetworkTransaction(CreateSession(&session_deps)));
4961
[email protected]1c773ea12009-04-28 19:58:424962 MockWrite data_writes[] = {
4963 MockWrite("GET / HTTP/1.1\r\n"
4964 "Host: www.google.com\r\n"
4965 "Connection: keep-alive\r\n"
4966 "Referer: http://the.previous.site.com/\r\n\r\n"),
4967 };
4968
4969 // Lastly, the server responds with the actual content.
4970 MockRead data_reads[] = {
4971 MockRead("HTTP/1.0 200 OK\r\n"),
4972 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4973 MockRead("Content-Length: 100\r\n\r\n"),
4974 MockRead(false, OK),
4975 };
4976
[email protected]31a2bfe2010-02-09 08:03:394977 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4978 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594979 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424980
4981 TestCompletionCallback callback;
4982
[email protected]5a1d7ca2010-04-28 20:12:274983 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424984 EXPECT_EQ(ERR_IO_PENDING, rv);
4985
4986 rv = callback.WaitForResult();
4987 EXPECT_EQ(OK, rv);
4988}
4989
4990TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424991 HttpRequestInfo request;
4992 request.method = "POST";
4993 request.url = GURL("http://www.google.com/");
4994
[email protected]cb9bf6ca2011-01-28 13:15:274995 SessionDependencies session_deps;
4996 scoped_ptr<HttpTransaction> trans(
4997 new HttpNetworkTransaction(CreateSession(&session_deps)));
4998
[email protected]1c773ea12009-04-28 19:58:424999 MockWrite data_writes[] = {
5000 MockWrite("POST / HTTP/1.1\r\n"
5001 "Host: www.google.com\r\n"
5002 "Connection: keep-alive\r\n"
5003 "Content-Length: 0\r\n\r\n"),
5004 };
5005
5006 // Lastly, the server responds with the actual content.
5007 MockRead data_reads[] = {
5008 MockRead("HTTP/1.0 200 OK\r\n"),
5009 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5010 MockRead("Content-Length: 100\r\n\r\n"),
5011 MockRead(false, OK),
5012 };
5013
[email protected]31a2bfe2010-02-09 08:03:395014 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5015 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595016 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425017
5018 TestCompletionCallback callback;
5019
[email protected]5a1d7ca2010-04-28 20:12:275020 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425021 EXPECT_EQ(ERR_IO_PENDING, rv);
5022
5023 rv = callback.WaitForResult();
5024 EXPECT_EQ(OK, rv);
5025}
5026
5027TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425028 HttpRequestInfo request;
5029 request.method = "PUT";
5030 request.url = GURL("http://www.google.com/");
5031
[email protected]cb9bf6ca2011-01-28 13:15:275032 SessionDependencies session_deps;
5033 scoped_ptr<HttpTransaction> trans(
5034 new HttpNetworkTransaction(CreateSession(&session_deps)));
5035
[email protected]1c773ea12009-04-28 19:58:425036 MockWrite data_writes[] = {
5037 MockWrite("PUT / HTTP/1.1\r\n"
5038 "Host: www.google.com\r\n"
5039 "Connection: keep-alive\r\n"
5040 "Content-Length: 0\r\n\r\n"),
5041 };
5042
5043 // Lastly, the server responds with the actual content.
5044 MockRead data_reads[] = {
5045 MockRead("HTTP/1.0 200 OK\r\n"),
5046 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5047 MockRead("Content-Length: 100\r\n\r\n"),
5048 MockRead(false, OK),
5049 };
5050
[email protected]31a2bfe2010-02-09 08:03:395051 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5052 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595053 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425054
5055 TestCompletionCallback callback;
5056
[email protected]5a1d7ca2010-04-28 20:12:275057 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425058 EXPECT_EQ(ERR_IO_PENDING, rv);
5059
5060 rv = callback.WaitForResult();
5061 EXPECT_EQ(OK, rv);
5062}
5063
5064TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425065 HttpRequestInfo request;
5066 request.method = "HEAD";
5067 request.url = GURL("http://www.google.com/");
5068
[email protected]cb9bf6ca2011-01-28 13:15:275069 SessionDependencies session_deps;
5070 scoped_ptr<HttpTransaction> trans(
5071 new HttpNetworkTransaction(CreateSession(&session_deps)));
5072
[email protected]1c773ea12009-04-28 19:58:425073 MockWrite data_writes[] = {
5074 MockWrite("HEAD / HTTP/1.1\r\n"
5075 "Host: www.google.com\r\n"
5076 "Connection: keep-alive\r\n"
5077 "Content-Length: 0\r\n\r\n"),
5078 };
5079
5080 // Lastly, the server responds with the actual content.
5081 MockRead data_reads[] = {
5082 MockRead("HTTP/1.0 200 OK\r\n"),
5083 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5084 MockRead("Content-Length: 100\r\n\r\n"),
5085 MockRead(false, OK),
5086 };
5087
[email protected]31a2bfe2010-02-09 08:03:395088 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5089 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595090 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425091
5092 TestCompletionCallback callback;
5093
[email protected]5a1d7ca2010-04-28 20:12:275094 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425095 EXPECT_EQ(ERR_IO_PENDING, rv);
5096
5097 rv = callback.WaitForResult();
5098 EXPECT_EQ(OK, rv);
5099}
5100
5101TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425102 HttpRequestInfo request;
5103 request.method = "GET";
5104 request.url = GURL("http://www.google.com/");
5105 request.load_flags = LOAD_BYPASS_CACHE;
5106
[email protected]cb9bf6ca2011-01-28 13:15:275107 SessionDependencies session_deps;
5108 scoped_ptr<HttpTransaction> trans(
5109 new HttpNetworkTransaction(CreateSession(&session_deps)));
5110
[email protected]1c773ea12009-04-28 19:58:425111 MockWrite data_writes[] = {
5112 MockWrite("GET / HTTP/1.1\r\n"
5113 "Host: www.google.com\r\n"
5114 "Connection: keep-alive\r\n"
5115 "Pragma: no-cache\r\n"
5116 "Cache-Control: no-cache\r\n\r\n"),
5117 };
5118
5119 // Lastly, the server responds with the actual content.
5120 MockRead data_reads[] = {
5121 MockRead("HTTP/1.0 200 OK\r\n"),
5122 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5123 MockRead("Content-Length: 100\r\n\r\n"),
5124 MockRead(false, OK),
5125 };
5126
[email protected]31a2bfe2010-02-09 08:03:395127 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5128 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595129 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425130
5131 TestCompletionCallback callback;
5132
[email protected]5a1d7ca2010-04-28 20:12:275133 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425134 EXPECT_EQ(ERR_IO_PENDING, rv);
5135
5136 rv = callback.WaitForResult();
5137 EXPECT_EQ(OK, rv);
5138}
5139
5140TEST_F(HttpNetworkTransactionTest,
5141 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425142 HttpRequestInfo request;
5143 request.method = "GET";
5144 request.url = GURL("http://www.google.com/");
5145 request.load_flags = LOAD_VALIDATE_CACHE;
5146
[email protected]cb9bf6ca2011-01-28 13:15:275147 SessionDependencies session_deps;
5148 scoped_ptr<HttpTransaction> trans(
5149 new HttpNetworkTransaction(CreateSession(&session_deps)));
5150
[email protected]1c773ea12009-04-28 19:58:425151 MockWrite data_writes[] = {
5152 MockWrite("GET / HTTP/1.1\r\n"
5153 "Host: www.google.com\r\n"
5154 "Connection: keep-alive\r\n"
5155 "Cache-Control: max-age=0\r\n\r\n"),
5156 };
5157
5158 // Lastly, the server responds with the actual content.
5159 MockRead data_reads[] = {
5160 MockRead("HTTP/1.0 200 OK\r\n"),
5161 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5162 MockRead("Content-Length: 100\r\n\r\n"),
5163 MockRead(false, OK),
5164 };
5165
[email protected]31a2bfe2010-02-09 08:03:395166 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5167 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595168 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425169
5170 TestCompletionCallback callback;
5171
[email protected]5a1d7ca2010-04-28 20:12:275172 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425173 EXPECT_EQ(ERR_IO_PENDING, rv);
5174
5175 rv = callback.WaitForResult();
5176 EXPECT_EQ(OK, rv);
5177}
5178
5179TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425180 HttpRequestInfo request;
5181 request.method = "GET";
5182 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435183 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425184
[email protected]cb9bf6ca2011-01-28 13:15:275185 SessionDependencies session_deps;
5186 scoped_ptr<HttpTransaction> trans(
5187 new HttpNetworkTransaction(CreateSession(&session_deps)));
5188
[email protected]1c773ea12009-04-28 19:58:425189 MockWrite data_writes[] = {
5190 MockWrite("GET / HTTP/1.1\r\n"
5191 "Host: www.google.com\r\n"
5192 "Connection: keep-alive\r\n"
5193 "FooHeader: Bar\r\n\r\n"),
5194 };
5195
5196 // Lastly, the server responds with the actual content.
5197 MockRead data_reads[] = {
5198 MockRead("HTTP/1.0 200 OK\r\n"),
5199 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5200 MockRead("Content-Length: 100\r\n\r\n"),
5201 MockRead(false, OK),
5202 };
5203
[email protected]31a2bfe2010-02-09 08:03:395204 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5205 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595206 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425207
5208 TestCompletionCallback callback;
5209
[email protected]5a1d7ca2010-04-28 20:12:275210 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425211 EXPECT_EQ(ERR_IO_PENDING, rv);
5212
5213 rv = callback.WaitForResult();
5214 EXPECT_EQ(OK, rv);
5215}
5216
[email protected]270c6412010-03-29 22:02:475217TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475218 HttpRequestInfo request;
5219 request.method = "GET";
5220 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435221 request.extra_headers.SetHeader("referer", "www.foo.com");
5222 request.extra_headers.SetHeader("hEllo", "Kitty");
5223 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475224
[email protected]cb9bf6ca2011-01-28 13:15:275225 SessionDependencies session_deps;
5226 scoped_ptr<HttpTransaction> trans(
5227 new HttpNetworkTransaction(CreateSession(&session_deps)));
5228
[email protected]270c6412010-03-29 22:02:475229 MockWrite data_writes[] = {
5230 MockWrite("GET / HTTP/1.1\r\n"
5231 "Host: www.google.com\r\n"
5232 "Connection: keep-alive\r\n"
[email protected]c10450102011-06-27 09:06:165233 "referer: www.foo.com\r\n"
[email protected]270c6412010-03-29 22:02:475234 "hEllo: Kitty\r\n"
5235 "FoO: bar\r\n\r\n"),
5236 };
5237
5238 // Lastly, the server responds with the actual content.
5239 MockRead data_reads[] = {
5240 MockRead("HTTP/1.0 200 OK\r\n"),
5241 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5242 MockRead("Content-Length: 100\r\n\r\n"),
5243 MockRead(false, OK),
5244 };
5245
5246 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5247 data_writes, arraysize(data_writes));
5248 session_deps.socket_factory.AddSocketDataProvider(&data);
5249
5250 TestCompletionCallback callback;
5251
[email protected]5a1d7ca2010-04-28 20:12:275252 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:475253 EXPECT_EQ(ERR_IO_PENDING, rv);
5254
5255 rv = callback.WaitForResult();
5256 EXPECT_EQ(OK, rv);
5257}
5258
[email protected]3cd17242009-06-23 02:59:025259TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275260 HttpRequestInfo request;
5261 request.method = "GET";
5262 request.url = GURL("http://www.google.com/");
5263 request.load_flags = 0;
5264
[email protected]80d6524d2009-08-18 03:58:095265 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005266 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025267
5268 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435269 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025270
[email protected]3cd17242009-06-23 02:59:025271 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5272 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5273
5274 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355275 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025276 MockWrite("GET / HTTP/1.1\r\n"
5277 "Host: www.google.com\r\n"
5278 "Connection: keep-alive\r\n\r\n")
5279 };
5280
5281 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595282 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025283 MockRead("HTTP/1.0 200 OK\r\n"),
5284 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5285 MockRead("Payload"),
5286 MockRead(false, OK)
5287 };
5288
[email protected]31a2bfe2010-02-09 08:03:395289 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5290 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595291 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025292
5293 TestCompletionCallback callback;
5294
[email protected]5a1d7ca2010-04-28 20:12:275295 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025296 EXPECT_EQ(ERR_IO_PENDING, rv);
5297
5298 rv = callback.WaitForResult();
5299 EXPECT_EQ(OK, rv);
5300
5301 const HttpResponseInfo* response = trans->GetResponseInfo();
5302 EXPECT_FALSE(response == NULL);
5303
5304 std::string response_text;
5305 rv = ReadTransaction(trans.get(), &response_text);
5306 EXPECT_EQ(OK, rv);
5307 EXPECT_EQ("Payload", response_text);
5308}
5309
5310TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275311 HttpRequestInfo request;
5312 request.method = "GET";
5313 request.url = GURL("https://www.google.com/");
5314 request.load_flags = 0;
5315
[email protected]80d6524d2009-08-18 03:58:095316 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005317 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025318
5319 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435320 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025321
[email protected]3cd17242009-06-23 02:59:025322 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5323 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5324
5325 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355326 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5327 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025328 MockWrite("GET / HTTP/1.1\r\n"
5329 "Host: www.google.com\r\n"
5330 "Connection: keep-alive\r\n\r\n")
5331 };
5332
5333 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355334 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5335 arraysize(read_buffer)),
5336 MockRead("HTTP/1.0 200 OK\r\n"),
5337 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5338 MockRead("Payload"),
5339 MockRead(false, OK)
5340 };
5341
[email protected]31a2bfe2010-02-09 08:03:395342 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5343 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595344 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355345
[email protected]5ecc992a42009-11-11 01:41:595346 SSLSocketDataProvider ssl(true, OK);
5347 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355348
5349 TestCompletionCallback callback;
5350
[email protected]5a1d7ca2010-04-28 20:12:275351 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355352 EXPECT_EQ(ERR_IO_PENDING, rv);
5353
5354 rv = callback.WaitForResult();
5355 EXPECT_EQ(OK, rv);
5356
5357 const HttpResponseInfo* response = trans->GetResponseInfo();
5358 EXPECT_FALSE(response == NULL);
5359
5360 std::string response_text;
5361 rv = ReadTransaction(trans.get(), &response_text);
5362 EXPECT_EQ(OK, rv);
5363 EXPECT_EQ("Payload", response_text);
5364}
5365
5366TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275367 HttpRequestInfo request;
5368 request.method = "GET";
5369 request.url = GURL("http://www.google.com/");
5370 request.load_flags = 0;
5371
[email protected]80d6524d2009-08-18 03:58:095372 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005373 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355374
5375 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435376 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355377
[email protected]e0c27be2009-07-15 13:09:355378 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5379 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375380 const char kSOCKS5OkRequest[] = {
5381 0x05, // Version
5382 0x01, // Command (CONNECT)
5383 0x00, // Reserved.
5384 0x03, // Address type (DOMAINNAME).
5385 0x0E, // Length of domain (14)
5386 // Domain string:
5387 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5388 0x00, 0x50, // 16-bit port (80)
5389 };
[email protected]e0c27be2009-07-15 13:09:355390 const char kSOCKS5OkResponse[] =
5391 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5392
5393 MockWrite data_writes[] = {
5394 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5395 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5396 MockWrite("GET / HTTP/1.1\r\n"
5397 "Host: www.google.com\r\n"
5398 "Connection: keep-alive\r\n\r\n")
5399 };
5400
5401 MockRead data_reads[] = {
5402 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5403 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5404 MockRead("HTTP/1.0 200 OK\r\n"),
5405 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5406 MockRead("Payload"),
5407 MockRead(false, OK)
5408 };
5409
[email protected]31a2bfe2010-02-09 08:03:395410 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5411 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595412 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355413
5414 TestCompletionCallback callback;
5415
[email protected]5a1d7ca2010-04-28 20:12:275416 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355417 EXPECT_EQ(ERR_IO_PENDING, rv);
5418
5419 rv = callback.WaitForResult();
5420 EXPECT_EQ(OK, rv);
5421
5422 const HttpResponseInfo* response = trans->GetResponseInfo();
5423 EXPECT_FALSE(response == NULL);
5424
5425 std::string response_text;
5426 rv = ReadTransaction(trans.get(), &response_text);
5427 EXPECT_EQ(OK, rv);
5428 EXPECT_EQ("Payload", response_text);
5429}
5430
5431TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275432 HttpRequestInfo request;
5433 request.method = "GET";
5434 request.url = GURL("https://www.google.com/");
5435 request.load_flags = 0;
5436
[email protected]80d6524d2009-08-18 03:58:095437 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005438 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355439
5440 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435441 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355442
[email protected]e0c27be2009-07-15 13:09:355443 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5444 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375445 const unsigned char kSOCKS5OkRequest[] = {
5446 0x05, // Version
5447 0x01, // Command (CONNECT)
5448 0x00, // Reserved.
5449 0x03, // Address type (DOMAINNAME).
5450 0x0E, // Length of domain (14)
5451 // Domain string:
5452 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5453 0x01, 0xBB, // 16-bit port (443)
5454 };
5455
[email protected]e0c27be2009-07-15 13:09:355456 const char kSOCKS5OkResponse[] =
5457 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5458
5459 MockWrite data_writes[] = {
5460 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5461 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5462 arraysize(kSOCKS5OkRequest)),
5463 MockWrite("GET / HTTP/1.1\r\n"
5464 "Host: www.google.com\r\n"
5465 "Connection: keep-alive\r\n\r\n")
5466 };
5467
5468 MockRead data_reads[] = {
5469 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5470 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025471 MockRead("HTTP/1.0 200 OK\r\n"),
5472 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5473 MockRead("Payload"),
5474 MockRead(false, OK)
5475 };
5476
[email protected]31a2bfe2010-02-09 08:03:395477 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5478 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595479 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025480
[email protected]5ecc992a42009-11-11 01:41:595481 SSLSocketDataProvider ssl(true, OK);
5482 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025483
5484 TestCompletionCallback callback;
5485
[email protected]5a1d7ca2010-04-28 20:12:275486 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025487 EXPECT_EQ(ERR_IO_PENDING, rv);
5488
5489 rv = callback.WaitForResult();
5490 EXPECT_EQ(OK, rv);
5491
5492 const HttpResponseInfo* response = trans->GetResponseInfo();
5493 EXPECT_FALSE(response == NULL);
5494
5495 std::string response_text;
5496 rv = ReadTransaction(trans.get(), &response_text);
5497 EXPECT_EQ(OK, rv);
5498 EXPECT_EQ("Payload", response_text);
5499}
5500
[email protected]04e5be32009-06-26 20:00:315501// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065502
5503struct GroupNameTest {
5504 std::string proxy_server;
5505 std::string url;
5506 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185507 bool ssl;
[email protected]2d731a32010-04-29 01:04:065508};
5509
5510scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8b114dd72011-03-25 05:33:025511 SessionDependencies* session_deps) {
5512 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps));
[email protected]2d731a32010-04-29 01:04:065513
5514 HttpAlternateProtocols* alternate_protocols =
5515 session->mutable_alternate_protocols();
5516 alternate_protocols->SetAlternateProtocolFor(
5517 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:355518 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065519
5520 return session;
5521}
5522
5523int GroupNameTransactionHelper(
5524 const std::string& url,
5525 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065526 HttpRequestInfo request;
5527 request.method = "GET";
5528 request.url = GURL(url);
5529 request.load_flags = 0;
5530
[email protected]cb9bf6ca2011-01-28 13:15:275531 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5532
[email protected]2d731a32010-04-29 01:04:065533 TestCompletionCallback callback;
5534
5535 // We do not complete this request, the dtor will clean the transaction up.
5536 return trans->Start(&request, &callback, BoundNetLog());
5537}
5538
5539TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5540 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315541 {
[email protected]2d731a32010-04-29 01:04:065542 "", // unused
[email protected]04e5be32009-06-26 20:00:315543 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545544 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185545 false,
[email protected]2ff8b312010-04-26 22:20:545546 },
5547 {
[email protected]2d731a32010-04-29 01:04:065548 "", // unused
[email protected]2ff8b312010-04-26 22:20:545549 "http://[2001:1418:13:1::25]/direct",
5550 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185551 false,
[email protected]04e5be32009-06-26 20:00:315552 },
[email protected]04e5be32009-06-26 20:00:315553
5554 // SSL Tests
5555 {
[email protected]2d731a32010-04-29 01:04:065556 "", // unused
[email protected]04e5be32009-06-26 20:00:315557 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025558 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185559 true,
[email protected]04e5be32009-06-26 20:00:315560 },
5561 {
[email protected]2d731a32010-04-29 01:04:065562 "", // unused
5563 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025564 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185565 true,
[email protected]04e5be32009-06-26 20:00:315566 },
5567 {
[email protected]2d731a32010-04-29 01:04:065568 "", // unused
[email protected]2ff8b312010-04-26 22:20:545569 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025570 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185571 true,
[email protected]2ff8b312010-04-26 22:20:545572 },
[email protected]2d731a32010-04-29 01:04:065573 };
[email protected]2ff8b312010-04-26 22:20:545574
[email protected]8e6441ca2010-08-19 05:56:385575 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065576
5577 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025578 SessionDependencies session_deps(
5579 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065580 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025581 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065582
5583 HttpNetworkSessionPeer peer(session);
[email protected]ab739042011-04-07 15:22:285584 CaptureGroupNameTransportSocketPool* transport_conn_pool =
5585 new CaptureGroupNameTransportSocketPool(NULL, NULL);
5586 peer.SetTransportSocketPool(transport_conn_pool);
[email protected]2431756e2010-09-29 20:26:135587 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345588 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185589 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065590
5591 EXPECT_EQ(ERR_IO_PENDING,
5592 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185593 if (tests[i].ssl)
5594 EXPECT_EQ(tests[i].expected_group_name,
5595 ssl_conn_pool->last_group_name_received());
5596 else
5597 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:285598 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065599 }
5600
[email protected]8e6441ca2010-08-19 05:56:385601 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065602}
5603
5604TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5605 const GroupNameTest tests[] = {
5606 {
5607 "http_proxy",
5608 "http://www.google.com/http_proxy_normal",
5609 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185610 false,
[email protected]2d731a32010-04-29 01:04:065611 },
5612
5613 // SSL Tests
5614 {
5615 "http_proxy",
5616 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025617 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185618 true,
[email protected]2d731a32010-04-29 01:04:065619 },
[email protected]af3490e2010-10-16 21:02:295620
[email protected]9faeded92010-04-29 20:03:055621 {
5622 "http_proxy",
5623 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025624 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185625 true,
[email protected]9faeded92010-04-29 20:03:055626 },
[email protected]2d731a32010-04-29 01:04:065627 };
5628
[email protected]8e6441ca2010-08-19 05:56:385629 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065630
5631 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025632 SessionDependencies session_deps(
5633 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065634 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025635 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065636
5637 HttpNetworkSessionPeer peer(session);
5638
[email protected]e60e47a2010-07-14 03:37:185639 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135640 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:345641 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185642 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135643 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345644 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185645 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065646
5647 EXPECT_EQ(ERR_IO_PENDING,
5648 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185649 if (tests[i].ssl)
5650 EXPECT_EQ(tests[i].expected_group_name,
5651 ssl_conn_pool->last_group_name_received());
5652 else
5653 EXPECT_EQ(tests[i].expected_group_name,
5654 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065655 }
5656
[email protected]8e6441ca2010-08-19 05:56:385657 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065658}
5659
5660TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5661 const GroupNameTest tests[] = {
5662 {
5663 "socks4://socks_proxy:1080",
5664 "http://www.google.com/socks4_direct",
5665 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185666 false,
[email protected]2d731a32010-04-29 01:04:065667 },
5668 {
5669 "socks5://socks_proxy:1080",
5670 "http://www.google.com/socks5_direct",
5671 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185672 false,
[email protected]2d731a32010-04-29 01:04:065673 },
5674
5675 // SSL Tests
5676 {
5677 "socks4://socks_proxy:1080",
5678 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025679 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185680 true,
[email protected]2d731a32010-04-29 01:04:065681 },
5682 {
5683 "socks5://socks_proxy:1080",
5684 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025685 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185686 true,
[email protected]2d731a32010-04-29 01:04:065687 },
[email protected]af3490e2010-10-16 21:02:295688
[email protected]9faeded92010-04-29 20:03:055689 {
5690 "socks4://socks_proxy:1080",
5691 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025692 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185693 true,
[email protected]9faeded92010-04-29 20:03:055694 },
[email protected]04e5be32009-06-26 20:00:315695 };
5696
[email protected]8e6441ca2010-08-19 05:56:385697 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545698
[email protected]04e5be32009-06-26 20:00:315699 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025700 SessionDependencies session_deps(
5701 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065702 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025703 SetupSessionForGroupNameTests(&session_deps));
5704
[email protected]2d731a32010-04-29 01:04:065705 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315706
[email protected]e60e47a2010-07-14 03:37:185707 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135708 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345709 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185710 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135711 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345712 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185713 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315714
[email protected]5695b8c2009-09-30 21:36:435715 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315716
[email protected]2d731a32010-04-29 01:04:065717 EXPECT_EQ(ERR_IO_PENDING,
5718 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185719 if (tests[i].ssl)
5720 EXPECT_EQ(tests[i].expected_group_name,
5721 ssl_conn_pool->last_group_name_received());
5722 else
5723 EXPECT_EQ(tests[i].expected_group_name,
5724 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315725 }
[email protected]2ff8b312010-04-26 22:20:545726
[email protected]8e6441ca2010-08-19 05:56:385727 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315728}
5729
[email protected]9172a982009-06-06 00:30:255730TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275731 HttpRequestInfo request;
5732 request.method = "GET";
5733 request.url = GURL("http://www.google.com/");
5734
[email protected]5c6a17e2009-06-10 00:54:545735 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005736 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325737
[email protected]69719062010-01-05 20:09:215738 // This simulates failure resolving all hostnames; that means we will fail
5739 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325740 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5741
[email protected]9172a982009-06-06 00:30:255742 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435743 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255744
[email protected]9172a982009-06-06 00:30:255745 TestCompletionCallback callback;
5746
[email protected]5a1d7ca2010-04-28 20:12:275747 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255748 EXPECT_EQ(ERR_IO_PENDING, rv);
5749
[email protected]9172a982009-06-06 00:30:255750 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015751 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255752}
5753
[email protected]f3e6c1e2009-06-15 20:52:125754// Host resolution observer used by
5755// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5756// resovle requests are issued with a referrer of |expected_referrer|.
5757class ResolutionReferrerObserver : public HostResolver::Observer {
5758 public:
5759 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5760 : expected_referrer_(expected_referrer),
5761 called_start_with_referrer_(false),
5762 called_finish_with_referrer_(false) {
5763 }
5764
5765 virtual void OnStartResolution(int id,
5766 const HostResolver::RequestInfo& info) {
5767 if (info.referrer() == expected_referrer_)
5768 called_start_with_referrer_ = true;
5769 }
5770
5771 virtual void OnFinishResolutionWithStatus(
5772 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5773 if (info.referrer() == expected_referrer_)
5774 called_finish_with_referrer_ = true;
5775 }
5776
[email protected]eb255d32009-06-17 02:11:035777 virtual void OnCancelResolution(int id,
5778 const HostResolver::RequestInfo& info ) {
5779 FAIL() << "Should not be cancelling any requests!";
5780 }
5781
[email protected]f3e6c1e2009-06-15 20:52:125782 bool did_complete_with_expected_referrer() const {
5783 return called_start_with_referrer_ && called_finish_with_referrer_;
5784 }
5785
5786 private:
5787 GURL expected_referrer_;
5788 bool called_start_with_referrer_;
5789 bool called_finish_with_referrer_;
5790
5791 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5792};
5793
5794// Make sure that when HostResolver::Resolve() is invoked, it passes through
5795// the "referrer". This is depended on by the DNS prefetch observer.
5796TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5797 GURL referrer = GURL("http://expected-referrer/");
5798 EXPECT_TRUE(referrer.is_valid());
5799 ResolutionReferrerObserver resolution_observer(referrer);
5800
[email protected]cb9bf6ca2011-01-28 13:15:275801 // Issue a request, containing an HTTP referrer.
5802 HttpRequestInfo request;
5803 request.method = "GET";
[email protected]cb9bf6ca2011-01-28 13:15:275804 request.url = GURL("http://www.google.com/");
[email protected]c10450102011-06-27 09:06:165805 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
5806 referrer.spec());
[email protected]cb9bf6ca2011-01-28 13:15:275807
[email protected]f3e6c1e2009-06-15 20:52:125808 SessionDependencies session_deps;
5809 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435810 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125811
5812 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145813 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125814
5815 // Connect up a mock socket which will fail when reading.
5816 MockRead data_reads[] = {
5817 MockRead(false, ERR_FAILED),
5818 };
[email protected]31a2bfe2010-02-09 08:03:395819 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595820 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125821
[email protected]f3e6c1e2009-06-15 20:52:125822 // Run the request until it fails reading from the socket.
5823 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275824 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125825 EXPECT_EQ(ERR_IO_PENDING, rv);
5826 rv = callback.WaitForResult();
5827 EXPECT_EQ(ERR_FAILED, rv);
5828
5829 // Check that the host resolution observer saw |referrer|.
5830 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5831}
5832
[email protected]685af592010-05-11 19:31:245833// Base test to make sure that when the load flags for a request specify to
5834// bypass the cache, the DNS cache is not used.
5835void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275836 // Issue a request, asking to bypass the cache(s).
5837 HttpRequestInfo request;
5838 request.method = "GET";
5839 request.load_flags = load_flags;
5840 request.url = GURL("http://www.google.com/");
5841
[email protected]3b9cca42009-06-16 01:08:285842 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325843
[email protected]a2c2fb92009-07-18 07:31:045844 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545845 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325846
[email protected]3b9cca42009-06-16 01:08:285847 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435848 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285849
5850 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5851 // a synchronous lookup.)
5852 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145853 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105854 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275855 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285856 EXPECT_EQ(OK, rv);
5857
5858 // Verify that it was added to host cache, by doing a subsequent async lookup
5859 // and confirming it completes synchronously.
5860 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465861 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105862 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275863 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325864 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285865
5866 // Inject a failure the next time that "www.google.com" is resolved. This way
5867 // we can tell if the next lookup hit the cache, or the "network".
5868 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325869 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285870
5871 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5872 // first read -- this won't be reached as the host resolution will fail first.
5873 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395874 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595875 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285876
[email protected]3b9cca42009-06-16 01:08:285877 // Run the request.
5878 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275879 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285880 ASSERT_EQ(ERR_IO_PENDING, rv);
5881 rv = callback.WaitForResult();
5882
5883 // If we bypassed the cache, we would have gotten a failure while resolving
5884 // "www.google.com".
5885 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5886}
5887
[email protected]685af592010-05-11 19:31:245888// There are multiple load flags that should trigger the host cache bypass.
5889// Test each in isolation:
5890TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5891 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5892}
5893
5894TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5895 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5896}
5897
5898TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5899 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5900}
5901
[email protected]0877e3d2009-10-17 22:29:575902// Make sure we can handle an error when writing the request.
5903TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5904 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275905 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575906
5907 HttpRequestInfo request;
5908 request.method = "GET";
5909 request.url = GURL("http://www.foo.com/");
5910 request.load_flags = 0;
5911
5912 MockWrite write_failure[] = {
5913 MockWrite(true, ERR_CONNECTION_RESET),
5914 };
[email protected]31a2bfe2010-02-09 08:03:395915 StaticSocketDataProvider data(NULL, 0,
5916 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595917 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575918
5919 TestCompletionCallback callback;
5920
5921 scoped_ptr<HttpTransaction> trans(
5922 new HttpNetworkTransaction(CreateSession(&session_deps)));
5923
[email protected]5a1d7ca2010-04-28 20:12:275924 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575925 EXPECT_EQ(ERR_IO_PENDING, rv);
5926
5927 rv = callback.WaitForResult();
5928 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5929}
5930
5931// Check that a connection closed after the start of the headers finishes ok.
5932TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5933 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275934 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575935
5936 HttpRequestInfo request;
5937 request.method = "GET";
5938 request.url = GURL("http://www.foo.com/");
5939 request.load_flags = 0;
5940
5941 MockRead data_reads[] = {
5942 MockRead("HTTP/1."),
5943 MockRead(false, OK),
5944 };
5945
[email protected]31a2bfe2010-02-09 08:03:395946 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595947 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575948
5949 TestCompletionCallback callback;
5950
5951 scoped_ptr<HttpTransaction> trans(
5952 new HttpNetworkTransaction(CreateSession(&session_deps)));
5953
[email protected]5a1d7ca2010-04-28 20:12:275954 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575955 EXPECT_EQ(ERR_IO_PENDING, rv);
5956
5957 rv = callback.WaitForResult();
5958 EXPECT_EQ(OK, rv);
5959
5960 const HttpResponseInfo* response = trans->GetResponseInfo();
5961 EXPECT_TRUE(response != NULL);
5962
5963 EXPECT_TRUE(response->headers != NULL);
5964 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5965
5966 std::string response_data;
5967 rv = ReadTransaction(trans.get(), &response_data);
5968 EXPECT_EQ(OK, rv);
5969 EXPECT_EQ("", response_data);
5970}
5971
5972// Make sure that a dropped connection while draining the body for auth
5973// restart does the right thing.
5974TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5975 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275976 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575977
5978 HttpRequestInfo request;
5979 request.method = "GET";
5980 request.url = GURL("http://www.google.com/");
5981 request.load_flags = 0;
5982
5983 MockWrite data_writes1[] = {
5984 MockWrite("GET / HTTP/1.1\r\n"
5985 "Host: www.google.com\r\n"
5986 "Connection: keep-alive\r\n\r\n"),
5987 };
5988
5989 MockRead data_reads1[] = {
5990 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5991 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5992 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5993 MockRead("Content-Length: 14\r\n\r\n"),
5994 MockRead("Unauth"),
5995 MockRead(true, ERR_CONNECTION_RESET),
5996 };
5997
[email protected]31a2bfe2010-02-09 08:03:395998 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5999 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:596000 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:576001
6002 // After calling trans->RestartWithAuth(), this is the request we should
6003 // be issuing -- the final header line contains the credentials.
6004 MockWrite data_writes2[] = {
6005 MockWrite("GET / HTTP/1.1\r\n"
6006 "Host: www.google.com\r\n"
6007 "Connection: keep-alive\r\n"
6008 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6009 };
6010
6011 // Lastly, the server responds with the actual content.
6012 MockRead data_reads2[] = {
6013 MockRead("HTTP/1.1 200 OK\r\n"),
6014 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6015 MockRead("Content-Length: 100\r\n\r\n"),
6016 MockRead(false, OK),
6017 };
6018
[email protected]31a2bfe2010-02-09 08:03:396019 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6020 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:596021 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:576022
6023 TestCompletionCallback callback1;
6024
[email protected]0b0bf032010-09-21 18:08:506025 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6026
[email protected]5a1d7ca2010-04-28 20:12:276027 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576028 EXPECT_EQ(ERR_IO_PENDING, rv);
6029
6030 rv = callback1.WaitForResult();
6031 EXPECT_EQ(OK, rv);
6032
6033 const HttpResponseInfo* response = trans->GetResponseInfo();
6034 EXPECT_FALSE(response == NULL);
6035
6036 // The password prompt info should have been set in response->auth_challenge.
6037 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6038
6039 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6040 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
6041 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6042
6043 TestCompletionCallback callback2;
6044
[email protected]13c8a092010-07-29 06:15:446045 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:576046 EXPECT_EQ(ERR_IO_PENDING, rv);
6047
6048 rv = callback2.WaitForResult();
6049 EXPECT_EQ(OK, rv);
6050
6051 response = trans->GetResponseInfo();
6052 EXPECT_FALSE(response == NULL);
6053 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6054 EXPECT_EQ(100, response->headers->GetContentLength());
6055}
6056
6057// Test HTTPS connections going through a proxy that sends extra data.
6058TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:006059 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:576060
6061 HttpRequestInfo request;
6062 request.method = "GET";
6063 request.url = GURL("https://www.google.com/");
6064 request.load_flags = 0;
6065
6066 MockRead proxy_reads[] = {
6067 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
6068 MockRead(false, OK)
6069 };
6070
[email protected]31a2bfe2010-02-09 08:03:396071 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:596072 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:576073
[email protected]5ecc992a42009-11-11 01:41:596074 session_deps.socket_factory.AddSocketDataProvider(&data);
6075 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:576076
6077 TestCompletionCallback callback;
6078
6079 session_deps.socket_factory.ResetNextMockIndexes();
6080
6081 scoped_ptr<HttpTransaction> trans(
6082 new HttpNetworkTransaction(CreateSession(&session_deps)));
6083
[email protected]5a1d7ca2010-04-28 20:12:276084 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576085 EXPECT_EQ(ERR_IO_PENDING, rv);
6086
6087 rv = callback.WaitForResult();
6088 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6089}
6090
[email protected]e22e1362009-11-23 21:31:126091TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:466092 HttpRequestInfo request;
6093 request.method = "GET";
6094 request.url = GURL("http://www.google.com/");
6095 request.load_flags = 0;
6096
[email protected]cb9bf6ca2011-01-28 13:15:276097 SessionDependencies session_deps;
6098 scoped_ptr<HttpTransaction> trans(
6099 new HttpNetworkTransaction(CreateSession(&session_deps)));
6100
[email protected]e22e1362009-11-23 21:31:126101 MockRead data_reads[] = {
6102 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6103 MockRead(false, OK),
6104 };
[email protected]9492e4a2010-02-24 00:58:466105
6106 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6107 session_deps.socket_factory.AddSocketDataProvider(&data);
6108
6109 TestCompletionCallback callback;
6110
[email protected]5a1d7ca2010-04-28 20:12:276111 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466112 EXPECT_EQ(ERR_IO_PENDING, rv);
6113
6114 EXPECT_EQ(OK, callback.WaitForResult());
6115
6116 const HttpResponseInfo* response = trans->GetResponseInfo();
6117 EXPECT_TRUE(response != NULL);
6118
6119 EXPECT_TRUE(response->headers != NULL);
6120 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6121
6122 std::string response_data;
6123 rv = ReadTransaction(trans.get(), &response_data);
6124 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126125}
6126
[email protected]95d88ffe2010-02-04 21:25:336127TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336128 HttpRequestInfo request;
6129 request.method = "POST";
6130 request.url = GURL("http://www.google.com/upload");
6131 request.upload_data = new UploadData;
6132 request.load_flags = 0;
6133
[email protected]cb9bf6ca2011-01-28 13:15:276134 SessionDependencies session_deps;
6135 scoped_ptr<HttpTransaction> trans(
6136 new HttpNetworkTransaction(CreateSession(&session_deps)));
6137
[email protected]95d88ffe2010-02-04 21:25:336138 FilePath temp_file_path;
6139 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6140 const uint64 kFakeSize = 100000; // file is actually blank
6141
6142 std::vector<UploadData::Element> elements;
6143 UploadData::Element element;
6144 element.SetToFilePath(temp_file_path);
6145 element.SetContentLength(kFakeSize);
6146 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536147 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:336148 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6149
6150 MockRead data_reads[] = {
6151 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6152 MockRead("hello world"),
6153 MockRead(false, OK),
6154 };
[email protected]31a2bfe2010-02-09 08:03:396155 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336156 session_deps.socket_factory.AddSocketDataProvider(&data);
6157
6158 TestCompletionCallback callback;
6159
[email protected]5a1d7ca2010-04-28 20:12:276160 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336161 EXPECT_EQ(ERR_IO_PENDING, rv);
6162
6163 rv = callback.WaitForResult();
6164 EXPECT_EQ(OK, rv);
6165
6166 const HttpResponseInfo* response = trans->GetResponseInfo();
6167 EXPECT_TRUE(response != NULL);
6168
6169 EXPECT_TRUE(response->headers != NULL);
6170 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6171
6172 std::string response_data;
6173 rv = ReadTransaction(trans.get(), &response_data);
6174 EXPECT_EQ(OK, rv);
6175 EXPECT_EQ("hello world", response_data);
6176
6177 file_util::Delete(temp_file_path, false);
6178}
6179
[email protected]6624b4622010-03-29 19:58:366180TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276181 HttpRequestInfo request;
6182 request.method = "POST";
6183 request.url = GURL("http://www.google.com/upload");
6184 request.upload_data = new UploadData;
6185 request.load_flags = 0;
6186
[email protected]6624b4622010-03-29 19:58:366187 // If we try to upload an unreadable file, the network stack should report
6188 // the file size as zero and upload zero bytes for that file.
6189 SessionDependencies session_deps;
6190 scoped_ptr<HttpTransaction> trans(
6191 new HttpNetworkTransaction(CreateSession(&session_deps)));
6192
6193 FilePath temp_file;
6194 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6195 std::string temp_file_content("Unreadable file.");
6196 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6197 temp_file_content.length()));
6198 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6199
[email protected]6624b4622010-03-29 19:58:366200 std::vector<UploadData::Element> elements;
6201 UploadData::Element element;
6202 element.SetToFilePath(temp_file);
6203 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536204 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366205
6206 MockRead data_reads[] = {
6207 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6208 MockRead(false, OK),
6209 };
6210 MockWrite data_writes[] = {
6211 MockWrite("POST /upload HTTP/1.1\r\n"
6212 "Host: www.google.com\r\n"
6213 "Connection: keep-alive\r\n"
6214 "Content-Length: 0\r\n\r\n"),
6215 MockWrite(false, OK),
6216 };
6217 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6218 arraysize(data_writes));
6219 session_deps.socket_factory.AddSocketDataProvider(&data);
6220
6221 TestCompletionCallback callback;
6222
[email protected]5a1d7ca2010-04-28 20:12:276223 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366224 EXPECT_EQ(ERR_IO_PENDING, rv);
6225
6226 rv = callback.WaitForResult();
6227 EXPECT_EQ(OK, rv);
6228
6229 const HttpResponseInfo* response = trans->GetResponseInfo();
6230 EXPECT_TRUE(response != NULL);
6231 EXPECT_TRUE(response->headers != NULL);
6232 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6233
6234 file_util::Delete(temp_file, false);
6235}
6236
6237TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276238 HttpRequestInfo request;
6239 request.method = "POST";
6240 request.url = GURL("http://www.google.com/upload");
6241 request.upload_data = new UploadData;
6242 request.load_flags = 0;
6243
[email protected]6624b4622010-03-29 19:58:366244 SessionDependencies session_deps;
6245 scoped_ptr<HttpTransaction> trans(
6246 new HttpNetworkTransaction(CreateSession(&session_deps)));
6247
6248 FilePath temp_file;
6249 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6250 std::string temp_file_contents("Unreadable file.");
6251 std::string unreadable_contents(temp_file_contents.length(), '\0');
6252 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6253 temp_file_contents.length()));
6254
[email protected]6624b4622010-03-29 19:58:366255 std::vector<UploadData::Element> elements;
6256 UploadData::Element element;
6257 element.SetToFilePath(temp_file);
6258 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536259 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366260
6261 MockRead data_reads[] = {
6262 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6263 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6264 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6265
6266 MockRead("HTTP/1.1 200 OK\r\n"),
6267 MockRead("Content-Length: 0\r\n\r\n"),
6268 MockRead(false, OK),
6269 };
6270 MockWrite data_writes[] = {
6271 MockWrite("POST /upload HTTP/1.1\r\n"
6272 "Host: www.google.com\r\n"
6273 "Connection: keep-alive\r\n"
6274 "Content-Length: 16\r\n\r\n"),
6275 MockWrite(false, temp_file_contents.c_str()),
6276
6277 MockWrite("POST /upload HTTP/1.1\r\n"
6278 "Host: www.google.com\r\n"
6279 "Connection: keep-alive\r\n"
6280 "Content-Length: 16\r\n"
6281 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6282 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6283 MockWrite(false, OK),
6284 };
6285 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6286 arraysize(data_writes));
6287 session_deps.socket_factory.AddSocketDataProvider(&data);
6288
6289 TestCompletionCallback callback1;
6290
[email protected]5a1d7ca2010-04-28 20:12:276291 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366292 EXPECT_EQ(ERR_IO_PENDING, rv);
6293
6294 rv = callback1.WaitForResult();
6295 EXPECT_EQ(OK, rv);
6296
6297 const HttpResponseInfo* response = trans->GetResponseInfo();
6298 EXPECT_TRUE(response != NULL);
6299 EXPECT_TRUE(response->headers != NULL);
6300 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
6301
6302 // The password prompt info should have been set in response->auth_challenge.
6303 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6304 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6305 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
6306 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6307
6308 // Now make the file unreadable and try again.
6309 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6310
6311 TestCompletionCallback callback2;
6312
[email protected]13c8a092010-07-29 06:15:446313 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:366314 EXPECT_EQ(ERR_IO_PENDING, rv);
6315
6316 rv = callback2.WaitForResult();
6317 EXPECT_EQ(OK, rv);
6318
6319 response = trans->GetResponseInfo();
6320 EXPECT_TRUE(response != NULL);
6321 EXPECT_TRUE(response->headers != NULL);
6322 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6323 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6324
6325 file_util::Delete(temp_file, false);
6326}
6327
[email protected]aeefc9e82010-02-19 16:18:276328// Tests that changes to Auth realms are treated like auth rejections.
6329TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6330 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276331
6332 HttpRequestInfo request;
6333 request.method = "GET";
6334 request.url = GURL("http://www.google.com/");
6335 request.load_flags = 0;
6336
6337 // First transaction will request a resource and receive a Basic challenge
6338 // with realm="first_realm".
6339 MockWrite data_writes1[] = {
6340 MockWrite("GET / HTTP/1.1\r\n"
6341 "Host: www.google.com\r\n"
6342 "Connection: keep-alive\r\n"
6343 "\r\n"),
6344 };
6345 MockRead data_reads1[] = {
6346 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6347 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6348 "\r\n"),
6349 };
6350
6351 // After calling trans->RestartWithAuth(), provide an Authentication header
6352 // for first_realm. The server will reject and provide a challenge with
6353 // second_realm.
6354 MockWrite data_writes2[] = {
6355 MockWrite("GET / HTTP/1.1\r\n"
6356 "Host: www.google.com\r\n"
6357 "Connection: keep-alive\r\n"
6358 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6359 "\r\n"),
6360 };
6361 MockRead data_reads2[] = {
6362 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6363 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6364 "\r\n"),
6365 };
6366
6367 // This again fails, and goes back to first_realm. Make sure that the
6368 // entry is removed from cache.
6369 MockWrite data_writes3[] = {
6370 MockWrite("GET / HTTP/1.1\r\n"
6371 "Host: www.google.com\r\n"
6372 "Connection: keep-alive\r\n"
6373 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6374 "\r\n"),
6375 };
6376 MockRead data_reads3[] = {
6377 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6378 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6379 "\r\n"),
6380 };
6381
6382 // Try one last time (with the correct password) and get the resource.
6383 MockWrite data_writes4[] = {
6384 MockWrite("GET / HTTP/1.1\r\n"
6385 "Host: www.google.com\r\n"
6386 "Connection: keep-alive\r\n"
6387 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6388 "\r\n"),
6389 };
6390 MockRead data_reads4[] = {
6391 MockRead("HTTP/1.1 200 OK\r\n"
6392 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506393 "Content-Length: 5\r\n"
6394 "\r\n"
6395 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276396 };
6397
6398 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6399 data_writes1, arraysize(data_writes1));
6400 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6401 data_writes2, arraysize(data_writes2));
6402 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6403 data_writes3, arraysize(data_writes3));
6404 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6405 data_writes4, arraysize(data_writes4));
6406 session_deps.socket_factory.AddSocketDataProvider(&data1);
6407 session_deps.socket_factory.AddSocketDataProvider(&data2);
6408 session_deps.socket_factory.AddSocketDataProvider(&data3);
6409 session_deps.socket_factory.AddSocketDataProvider(&data4);
6410
6411 TestCompletionCallback callback1;
6412
[email protected]0b0bf032010-09-21 18:08:506413 scoped_ptr<HttpTransaction> trans(
6414 new HttpNetworkTransaction(CreateSession(&session_deps)));
6415
[email protected]aeefc9e82010-02-19 16:18:276416 // Issue the first request with Authorize headers. There should be a
6417 // password prompt for first_realm waiting to be filled in after the
6418 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:276419 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276420 EXPECT_EQ(ERR_IO_PENDING, rv);
6421 rv = callback1.WaitForResult();
6422 EXPECT_EQ(OK, rv);
6423 const HttpResponseInfo* response = trans->GetResponseInfo();
6424 ASSERT_FALSE(response == NULL);
6425 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6426 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6427 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6428 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6429
6430 // Issue the second request with an incorrect password. There should be a
6431 // password prompt for second_realm waiting to be filled in after the
6432 // transaction completes.
6433 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:446434 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:276435 EXPECT_EQ(ERR_IO_PENDING, rv);
6436 rv = callback2.WaitForResult();
6437 EXPECT_EQ(OK, rv);
6438 response = trans->GetResponseInfo();
6439 ASSERT_FALSE(response == NULL);
6440 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6441 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6442 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
6443 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6444
6445 // Issue the third request with another incorrect password. There should be
6446 // a password prompt for first_realm waiting to be filled in. If the password
6447 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6448 // first_realm was not correctly removed.
6449 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:446450 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:276451 EXPECT_EQ(ERR_IO_PENDING, rv);
6452 rv = callback3.WaitForResult();
6453 EXPECT_EQ(OK, rv);
6454 response = trans->GetResponseInfo();
6455 ASSERT_FALSE(response == NULL);
6456 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6457 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6458 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6459 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6460
6461 // Issue the fourth request with the correct password and username.
6462 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:446463 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:276464 EXPECT_EQ(ERR_IO_PENDING, rv);
6465 rv = callback4.WaitForResult();
6466 EXPECT_EQ(OK, rv);
6467 response = trans->GetResponseInfo();
6468 ASSERT_FALSE(response == NULL);
6469 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6470}
6471
[email protected]564b4912010-03-09 16:30:426472TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:386473 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
6474 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426475
[email protected]564b4912010-03-09 16:30:426476 SessionDependencies session_deps;
6477
6478 MockRead data_reads[] = {
6479 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356480 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426481 MockRead("hello world"),
6482 MockRead(false, OK),
6483 };
6484
6485 HttpRequestInfo request;
6486 request.method = "GET";
6487 request.url = GURL("http://www.google.com/");
6488 request.load_flags = 0;
6489
6490 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6491
6492 session_deps.socket_factory.AddSocketDataProvider(&data);
6493
6494 TestCompletionCallback callback;
6495
6496 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6497 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6498
[email protected]5a1d7ca2010-04-28 20:12:276499 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426500 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536501
[email protected]2fbaecf22010-07-22 22:20:356502 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426503 const HttpAlternateProtocols& alternate_protocols =
6504 session->alternate_protocols();
6505 EXPECT_FALSE(
6506 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6507
6508 EXPECT_EQ(OK, callback.WaitForResult());
6509
6510 const HttpResponseInfo* response = trans->GetResponseInfo();
6511 ASSERT_TRUE(response != NULL);
6512 ASSERT_TRUE(response->headers != NULL);
6513 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536514 EXPECT_FALSE(response->was_fetched_via_spdy);
6515 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:426516
6517 std::string response_data;
6518 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6519 EXPECT_EQ("hello world", response_data);
6520
6521 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6522 const HttpAlternateProtocols::PortProtocolPair alternate =
6523 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
6524 HttpAlternateProtocols::PortProtocolPair expected_alternate;
6525 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:356526 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426527 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426528
[email protected]8e6441ca2010-08-19 05:56:386529 HttpStreamFactory::set_use_alternate_protocols(false);
6530 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:426531}
6532
[email protected]8b95ed62011-03-18 18:12:036533TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386534 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426535 SessionDependencies session_deps;
6536
6537 HttpRequestInfo request;
6538 request.method = "GET";
6539 request.url = GURL("http://www.google.com/");
6540 request.load_flags = 0;
6541
6542 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6543 StaticSocketDataProvider first_data;
6544 first_data.set_connect_data(mock_connect);
6545 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6546
6547 MockRead data_reads[] = {
6548 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6549 MockRead("hello world"),
6550 MockRead(true, OK),
6551 };
6552 StaticSocketDataProvider second_data(
6553 data_reads, arraysize(data_reads), NULL, 0);
6554 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6555
[email protected]564b4912010-03-09 16:30:426556 TestCompletionCallback callback;
6557
6558 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6559
[email protected]2fbaecf22010-07-22 22:20:356560 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426561 HttpAlternateProtocols* alternate_protocols =
6562 session->mutable_alternate_protocols();
6563 alternate_protocols->SetAlternateProtocolFor(
6564 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:356565 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426566
6567 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6568
[email protected]5a1d7ca2010-04-28 20:12:276569 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426570 EXPECT_EQ(ERR_IO_PENDING, rv);
6571 EXPECT_EQ(OK, callback.WaitForResult());
6572
6573 const HttpResponseInfo* response = trans->GetResponseInfo();
6574 ASSERT_TRUE(response != NULL);
6575 ASSERT_TRUE(response->headers != NULL);
6576 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6577
6578 std::string response_data;
6579 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6580 EXPECT_EQ("hello world", response_data);
6581
6582 ASSERT_TRUE(
6583 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6584 const HttpAlternateProtocols::PortProtocolPair alternate =
6585 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6586 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386587 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426588}
6589
[email protected]2ff8b312010-04-26 22:20:546590TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386591 HttpStreamFactory::set_use_alternate_protocols(true);
6592 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546593 SessionDependencies session_deps;
6594
6595 HttpRequestInfo request;
6596 request.method = "GET";
6597 request.url = GURL("http://www.google.com/");
6598 request.load_flags = 0;
6599
6600 MockRead data_reads[] = {
6601 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356602 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546603 MockRead("hello world"),
6604 MockRead(true, OK),
6605 };
6606
6607 StaticSocketDataProvider first_transaction(
6608 data_reads, arraysize(data_reads), NULL, 0);
6609 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6610
6611 SSLSocketDataProvider ssl(true, OK);
6612 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356613 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536614 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546615 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6616
[email protected]2bd93022010-07-17 00:58:446617 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136618 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546619
[email protected]2bd93022010-07-17 00:58:446620 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6621 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546622 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136623 CreateMockRead(*resp),
6624 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546625 MockRead(true, 0, 0),
6626 };
6627
6628 scoped_refptr<DelayedSocketData> spdy_data(
6629 new DelayedSocketData(
6630 1, // wait for one write to finish before reading.
6631 spdy_reads, arraysize(spdy_reads),
6632 spdy_writes, arraysize(spdy_writes)));
6633 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6634
[email protected]2d6728692011-03-12 01:39:556635 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6636 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6637 NULL, 0, NULL, 0);
6638 hanging_non_alternate_protocol_socket.set_connect_data(
6639 never_finishing_connect);
6640 session_deps.socket_factory.AddSocketDataProvider(
6641 &hanging_non_alternate_protocol_socket);
6642
[email protected]2ff8b312010-04-26 22:20:546643 TestCompletionCallback callback;
6644
6645 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6646 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6647
[email protected]5a1d7ca2010-04-28 20:12:276648 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546649 EXPECT_EQ(ERR_IO_PENDING, rv);
6650 EXPECT_EQ(OK, callback.WaitForResult());
6651
6652 const HttpResponseInfo* response = trans->GetResponseInfo();
6653 ASSERT_TRUE(response != NULL);
6654 ASSERT_TRUE(response->headers != NULL);
6655 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6656
6657 std::string response_data;
6658 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6659 EXPECT_EQ("hello world", response_data);
6660
6661 trans.reset(new HttpNetworkTransaction(session));
6662
[email protected]5a1d7ca2010-04-28 20:12:276663 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546664 EXPECT_EQ(ERR_IO_PENDING, rv);
6665 EXPECT_EQ(OK, callback.WaitForResult());
6666
6667 response = trans->GetResponseInfo();
6668 ASSERT_TRUE(response != NULL);
6669 ASSERT_TRUE(response->headers != NULL);
6670 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536671 EXPECT_TRUE(response->was_fetched_via_spdy);
6672 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:546673
6674 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6675 EXPECT_EQ("hello!", response_data);
6676
[email protected]8e6441ca2010-08-19 05:56:386677 HttpStreamFactory::set_next_protos("");
6678 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546679}
6680
[email protected]2d6728692011-03-12 01:39:556681TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6682 HttpStreamFactory::set_use_alternate_protocols(true);
6683 HttpStreamFactory::set_next_protos(kExpectedNPNString);
6684 SessionDependencies session_deps;
6685
6686 HttpRequestInfo request;
6687 request.method = "GET";
6688 request.url = GURL("http://www.google.com/");
6689 request.load_flags = 0;
6690
6691 MockRead data_reads[] = {
6692 MockRead("HTTP/1.1 200 OK\r\n"),
6693 MockRead(kAlternateProtocolHttpHeader),
6694 MockRead("hello world"),
6695 MockRead(true, OK),
6696 };
6697
6698 StaticSocketDataProvider first_transaction(
6699 data_reads, arraysize(data_reads), NULL, 0);
6700 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6701 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6702
6703 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6704 StaticSocketDataProvider hanging_socket(
6705 NULL, 0, NULL, 0);
6706 hanging_socket.set_connect_data(never_finishing_connect);
6707 // Socket 2 and 3 are the hanging Alternate-Protocol and
6708 // non-Alternate-Protocol jobs from the 2nd transaction.
6709 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6710 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6711
6712 SSLSocketDataProvider ssl(true, OK);
6713 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6714 ssl.next_proto = "spdy/2";
6715 ssl.was_npn_negotiated = true;
6716 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6717
6718 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6719 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6720 MockWrite spdy_writes[] = {
6721 CreateMockWrite(*req1),
6722 CreateMockWrite(*req2),
6723 };
6724 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6725 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
6726 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6727 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
6728 MockRead spdy_reads[] = {
6729 CreateMockRead(*resp1),
6730 CreateMockRead(*data1),
6731 CreateMockRead(*resp2),
6732 CreateMockRead(*data2),
6733 MockRead(true, 0, 0),
6734 };
6735
6736 scoped_refptr<DelayedSocketData> spdy_data(
6737 new DelayedSocketData(
6738 2, // wait for writes to finish before reading.
6739 spdy_reads, arraysize(spdy_reads),
6740 spdy_writes, arraysize(spdy_writes)));
6741 // Socket 4 is the successful Alternate-Protocol for transaction 3.
6742 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6743
6744 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
6745 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6746
6747 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6748 TestCompletionCallback callback1;
6749 HttpNetworkTransaction trans1(session);
6750
6751 int rv = trans1.Start(&request, &callback1, BoundNetLog());
6752 EXPECT_EQ(ERR_IO_PENDING, rv);
6753 EXPECT_EQ(OK, callback1.WaitForResult());
6754
6755 const HttpResponseInfo* response = trans1.GetResponseInfo();
6756 ASSERT_TRUE(response != NULL);
6757 ASSERT_TRUE(response->headers != NULL);
6758 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6759
6760 std::string response_data;
6761 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
6762 EXPECT_EQ("hello world", response_data);
6763
6764 TestCompletionCallback callback2;
6765 HttpNetworkTransaction trans2(session);
6766 rv = trans2.Start(&request, &callback2, BoundNetLog());
6767 EXPECT_EQ(ERR_IO_PENDING, rv);
6768
6769 TestCompletionCallback callback3;
6770 HttpNetworkTransaction trans3(session);
6771 rv = trans3.Start(&request, &callback3, BoundNetLog());
6772 EXPECT_EQ(ERR_IO_PENDING, rv);
6773
6774 EXPECT_EQ(OK, callback2.WaitForResult());
6775 EXPECT_EQ(OK, callback3.WaitForResult());
6776
6777 response = trans2.GetResponseInfo();
6778 ASSERT_TRUE(response != NULL);
6779 ASSERT_TRUE(response->headers != NULL);
6780 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6781 EXPECT_TRUE(response->was_fetched_via_spdy);
6782 EXPECT_TRUE(response->was_npn_negotiated);
6783 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
6784 EXPECT_EQ("hello!", response_data);
6785
6786 response = trans3.GetResponseInfo();
6787 ASSERT_TRUE(response != NULL);
6788 ASSERT_TRUE(response->headers != NULL);
6789 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6790 EXPECT_TRUE(response->was_fetched_via_spdy);
6791 EXPECT_TRUE(response->was_npn_negotiated);
6792 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
6793 EXPECT_EQ("hello!", response_data);
6794
6795 HttpStreamFactory::set_next_protos("");
6796 HttpStreamFactory::set_use_alternate_protocols(false);
6797}
6798
6799TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
6800 HttpStreamFactory::set_use_alternate_protocols(true);
6801 HttpStreamFactory::set_next_protos(kExpectedNPNString);
6802 SessionDependencies session_deps;
6803
6804 HttpRequestInfo request;
6805 request.method = "GET";
6806 request.url = GURL("http://www.google.com/");
6807 request.load_flags = 0;
6808
6809 MockRead data_reads[] = {
6810 MockRead("HTTP/1.1 200 OK\r\n"),
6811 MockRead(kAlternateProtocolHttpHeader),
6812 MockRead("hello world"),
6813 MockRead(true, OK),
6814 };
6815
6816 StaticSocketDataProvider first_transaction(
6817 data_reads, arraysize(data_reads), NULL, 0);
6818 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6819
6820 SSLSocketDataProvider ssl(true, OK);
6821 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6822 ssl.next_proto = "spdy/2";
6823 ssl.was_npn_negotiated = true;
6824 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6825
6826 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6827 StaticSocketDataProvider hanging_alternate_protocol_socket(
6828 NULL, 0, NULL, 0);
6829 hanging_alternate_protocol_socket.set_connect_data(
6830 never_finishing_connect);
6831 session_deps.socket_factory.AddSocketDataProvider(
6832 &hanging_alternate_protocol_socket);
6833
6834 // 2nd request is just a copy of the first one, over HTTP again.
6835 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6836
6837 TestCompletionCallback callback;
6838
6839 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6840 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6841
6842 int rv = trans->Start(&request, &callback, BoundNetLog());
6843 EXPECT_EQ(ERR_IO_PENDING, rv);
6844 EXPECT_EQ(OK, callback.WaitForResult());
6845
6846 const HttpResponseInfo* response = trans->GetResponseInfo();
6847 ASSERT_TRUE(response != NULL);
6848 ASSERT_TRUE(response->headers != NULL);
6849 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6850
6851 std::string response_data;
6852 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6853 EXPECT_EQ("hello world", response_data);
6854
6855 trans.reset(new HttpNetworkTransaction(session));
6856
6857 rv = trans->Start(&request, &callback, BoundNetLog());
6858 EXPECT_EQ(ERR_IO_PENDING, rv);
6859 EXPECT_EQ(OK, callback.WaitForResult());
6860
6861 response = trans->GetResponseInfo();
6862 ASSERT_TRUE(response != NULL);
6863 ASSERT_TRUE(response->headers != NULL);
6864 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6865 EXPECT_FALSE(response->was_fetched_via_spdy);
6866 EXPECT_FALSE(response->was_npn_negotiated);
6867
6868 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6869 EXPECT_EQ("hello world", response_data);
6870
6871 HttpStreamFactory::set_next_protos("");
6872 HttpStreamFactory::set_use_alternate_protocols(false);
6873}
6874
[email protected]631f1322010-04-30 17:59:116875class CapturingProxyResolver : public ProxyResolver {
6876 public:
6877 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6878 virtual ~CapturingProxyResolver() {}
6879
6880 virtual int GetProxyForURL(const GURL& url,
6881 ProxyInfo* results,
6882 CompletionCallback* callback,
6883 RequestHandle* request,
6884 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406885 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6886 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426887 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116888 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426889 return OK;
[email protected]631f1322010-04-30 17:59:116890 }
6891
6892 virtual void CancelRequest(RequestHandle request) {
6893 NOTREACHED();
6894 }
6895
[email protected]1e605472010-12-16 21:41:406896 virtual void CancelSetPacScript() {
6897 NOTREACHED();
6898 }
6899
[email protected]24476402010-07-20 20:55:176900 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116901 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426902 return OK;
[email protected]631f1322010-04-30 17:59:116903 }
6904
[email protected]24476402010-07-20 20:55:176905 const std::vector<GURL>& resolved() const { return resolved_; }
6906
6907 private:
[email protected]631f1322010-04-30 17:59:116908 std::vector<GURL> resolved_;
6909
6910 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6911};
6912
[email protected]631f1322010-04-30 17:59:116913TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386914 HttpStreamFactory::set_use_alternate_protocols(true);
6915 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116916
6917 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426918 proxy_config.set_auto_detect(true);
6919 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116920
[email protected]631f1322010-04-30 17:59:116921 CapturingProxyResolver* capturing_proxy_resolver =
6922 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386923 SessionDependencies session_deps(new ProxyService(
6924 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6925 NULL));
[email protected]631f1322010-04-30 17:59:116926
6927 HttpRequestInfo request;
6928 request.method = "GET";
6929 request.url = GURL("http://www.google.com/");
6930 request.load_flags = 0;
6931
6932 MockRead data_reads[] = {
6933 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356934 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116935 MockRead("hello world"),
6936 MockRead(true, OK),
6937 };
6938
6939 StaticSocketDataProvider first_transaction(
6940 data_reads, arraysize(data_reads), NULL, 0);
6941 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6942
6943 SSLSocketDataProvider ssl(true, OK);
6944 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356945 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536946 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116947 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6948
[email protected]2bd93022010-07-17 00:58:446949 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116950 MockWrite spdy_writes[] = {
6951 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6952 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426953 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136954 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116955 };
6956
[email protected]d911f1b2010-05-05 22:39:426957 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6958
[email protected]2bd93022010-07-17 00:58:446959 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6960 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116961 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426962 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136963 CreateMockRead(*resp.get(), 4), // 2, 4
6964 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426965 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116966 };
6967
[email protected]d911f1b2010-05-05 22:39:426968 scoped_refptr<OrderedSocketData> spdy_data(
6969 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116970 spdy_reads, arraysize(spdy_reads),
6971 spdy_writes, arraysize(spdy_writes)));
6972 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6973
[email protected]2d6728692011-03-12 01:39:556974 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6975 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6976 NULL, 0, NULL, 0);
6977 hanging_non_alternate_protocol_socket.set_connect_data(
6978 never_finishing_connect);
6979 session_deps.socket_factory.AddSocketDataProvider(
6980 &hanging_non_alternate_protocol_socket);
6981
[email protected]631f1322010-04-30 17:59:116982 TestCompletionCallback callback;
6983
6984 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6985 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6986
6987 int rv = trans->Start(&request, &callback, BoundNetLog());
6988 EXPECT_EQ(ERR_IO_PENDING, rv);
6989 EXPECT_EQ(OK, callback.WaitForResult());
6990
6991 const HttpResponseInfo* response = trans->GetResponseInfo();
6992 ASSERT_TRUE(response != NULL);
6993 ASSERT_TRUE(response->headers != NULL);
6994 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536995 EXPECT_FALSE(response->was_fetched_via_spdy);
6996 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116997
6998 std::string response_data;
6999 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7000 EXPECT_EQ("hello world", response_data);
7001
7002 trans.reset(new HttpNetworkTransaction(session));
7003
7004 rv = trans->Start(&request, &callback, BoundNetLog());
7005 EXPECT_EQ(ERR_IO_PENDING, rv);
7006 EXPECT_EQ(OK, callback.WaitForResult());
7007
7008 response = trans->GetResponseInfo();
7009 ASSERT_TRUE(response != NULL);
7010 ASSERT_TRUE(response->headers != NULL);
7011 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537012 EXPECT_TRUE(response->was_fetched_via_spdy);
7013 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117014
7015 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7016 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:557017 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
[email protected]d911f1b2010-05-05 22:39:427018 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:117019 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:427020 EXPECT_EQ("https://www.google.com/",
7021 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:117022
[email protected]8e6441ca2010-08-19 05:56:387023 HttpStreamFactory::set_next_protos("");
7024 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:117025}
[email protected]631f1322010-04-30 17:59:117026
[email protected]2ff8b312010-04-26 22:20:547027TEST_F(HttpNetworkTransactionTest,
7028 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:387029 HttpStreamFactory::set_use_alternate_protocols(true);
7030 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:547031 SessionDependencies session_deps;
7032
7033 HttpRequestInfo request;
7034 request.method = "GET";
7035 request.url = GURL("http://www.google.com/");
7036 request.load_flags = 0;
7037
7038 MockRead data_reads[] = {
7039 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357040 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:547041 MockRead("hello world"),
7042 MockRead(true, OK),
7043 };
7044
7045 StaticSocketDataProvider first_transaction(
7046 data_reads, arraysize(data_reads), NULL, 0);
7047 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7048
7049 SSLSocketDataProvider ssl(true, OK);
7050 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357051 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:537052 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:547053 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:537054 // Make sure we use ssl for spdy here.
7055 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:547056
[email protected]2bd93022010-07-17 00:58:447057 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137058 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:547059
[email protected]2bd93022010-07-17 00:58:447060 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7061 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:547062 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:137063 CreateMockRead(*resp),
7064 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:547065 MockRead(true, 0, 0),
7066 };
7067
7068 scoped_refptr<DelayedSocketData> spdy_data(
7069 new DelayedSocketData(
7070 1, // wait for one write to finish before reading.
7071 spdy_reads, arraysize(spdy_reads),
7072 spdy_writes, arraysize(spdy_writes)));
7073 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7074
7075 TestCompletionCallback callback;
7076
7077 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7078
7079 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7080
[email protected]5a1d7ca2010-04-28 20:12:277081 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547082 EXPECT_EQ(ERR_IO_PENDING, rv);
7083 EXPECT_EQ(OK, callback.WaitForResult());
7084
7085 const HttpResponseInfo* response = trans->GetResponseInfo();
7086 ASSERT_TRUE(response != NULL);
7087 ASSERT_TRUE(response->headers != NULL);
7088 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7089
7090 std::string response_data;
7091 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7092 EXPECT_EQ("hello world", response_data);
7093
7094 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387095 HostPortPair host_port_pair("www.google.com", 443);
7096 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:547097 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:317098 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:287099 scoped_refptr<TransportSocketParams> transport_params(
7100 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
[email protected]02b0c342010-09-25 21:09:387101
7102 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7103 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:287104 connection->Init(host_port_pair.ToString(),
7105 transport_params,
7106 LOWEST,
7107 &callback,
7108 session->transport_socket_pool(),
[email protected]02b0c342010-09-25 21:09:387109 BoundNetLog()));
7110 EXPECT_EQ(OK, callback.WaitForResult());
7111
7112 SSLConfig ssl_config;
7113 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]9e1bdd32011-02-03 21:48:347114 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
7115 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7116 connection.release(), HostPortPair("" , 443), ssl_config,
7117 NULL /* ssl_host_info */, session_deps.cert_verifier.get(), NULL));
7118 EXPECT_EQ(ERR_IO_PENDING, ssl_connection->socket()->Connect(&callback));
[email protected]02b0c342010-09-25 21:09:387119 EXPECT_EQ(OK, callback.WaitForResult());
7120
[email protected]9e1bdd32011-02-03 21:48:347121 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
[email protected]02b0c342010-09-25 21:09:387122 true, OK));
7123
[email protected]2ff8b312010-04-26 22:20:547124 trans.reset(new HttpNetworkTransaction(session));
7125
[email protected]5a1d7ca2010-04-28 20:12:277126 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547127 EXPECT_EQ(ERR_IO_PENDING, rv);
7128 EXPECT_EQ(OK, callback.WaitForResult());
7129
7130 response = trans->GetResponseInfo();
7131 ASSERT_TRUE(response != NULL);
7132 ASSERT_TRUE(response->headers != NULL);
7133 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537134 EXPECT_TRUE(response->was_fetched_via_spdy);
7135 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:547136
7137 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7138 EXPECT_EQ("hello!", response_data);
7139
[email protected]8e6441ca2010-08-19 05:56:387140 HttpStreamFactory::set_next_protos("");
7141 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:427142}
7143
[email protected]044de0642010-06-17 10:42:157144// GenerateAuthToken is a mighty big test.
7145// It tests all permutation of GenerateAuthToken behavior:
7146// - Synchronous and Asynchronous completion.
7147// - OK or error on completion.
7148// - Direct connection, non-authenticating proxy, and authenticating proxy.
7149// - HTTP or HTTPS backend (to include proxy tunneling).
7150// - Non-authenticating and authenticating backend.
7151//
7152// In all, there are 44 reasonable permuations (for example, if there are
7153// problems generating an auth token for an authenticating proxy, we don't
7154// need to test all permutations of the backend server).
7155//
7156// The test proceeds by going over each of the configuration cases, and
7157// potentially running up to three rounds in each of the tests. The TestConfig
7158// specifies both the configuration for the test as well as the expectations
7159// for the results.
7160TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:507161 static const char kServer[] = "http://www.example.com";
7162 static const char kSecureServer[] = "https://www.example.com";
7163 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:157164 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7165
7166 enum AuthTiming {
7167 AUTH_NONE,
7168 AUTH_SYNC,
7169 AUTH_ASYNC,
7170 };
7171
7172 const MockWrite kGet(
7173 "GET / HTTP/1.1\r\n"
7174 "Host: www.example.com\r\n"
7175 "Connection: keep-alive\r\n\r\n");
7176 const MockWrite kGetProxy(
7177 "GET http://www.example.com/ HTTP/1.1\r\n"
7178 "Host: www.example.com\r\n"
7179 "Proxy-Connection: keep-alive\r\n\r\n");
7180 const MockWrite kGetAuth(
7181 "GET / HTTP/1.1\r\n"
7182 "Host: www.example.com\r\n"
7183 "Connection: keep-alive\r\n"
7184 "Authorization: auth_token\r\n\r\n");
7185 const MockWrite kGetProxyAuth(
7186 "GET http://www.example.com/ HTTP/1.1\r\n"
7187 "Host: www.example.com\r\n"
7188 "Proxy-Connection: keep-alive\r\n"
7189 "Proxy-Authorization: auth_token\r\n\r\n");
7190 const MockWrite kGetAuthThroughProxy(
7191 "GET http://www.example.com/ HTTP/1.1\r\n"
7192 "Host: www.example.com\r\n"
7193 "Proxy-Connection: keep-alive\r\n"
7194 "Authorization: auth_token\r\n\r\n");
7195 const MockWrite kGetAuthWithProxyAuth(
7196 "GET http://www.example.com/ HTTP/1.1\r\n"
7197 "Host: www.example.com\r\n"
7198 "Proxy-Connection: keep-alive\r\n"
7199 "Proxy-Authorization: auth_token\r\n"
7200 "Authorization: auth_token\r\n\r\n");
7201 const MockWrite kConnect(
7202 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7203 "Host: www.example.com\r\n"
7204 "Proxy-Connection: keep-alive\r\n\r\n");
7205 const MockWrite kConnectProxyAuth(
7206 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7207 "Host: www.example.com\r\n"
7208 "Proxy-Connection: keep-alive\r\n"
7209 "Proxy-Authorization: auth_token\r\n\r\n");
7210
7211 const MockRead kSuccess(
7212 "HTTP/1.1 200 OK\r\n"
7213 "Content-Type: text/html; charset=iso-8859-1\r\n"
7214 "Content-Length: 3\r\n\r\n"
7215 "Yes");
7216 const MockRead kFailure(
7217 "Should not be called.");
7218 const MockRead kServerChallenge(
7219 "HTTP/1.1 401 Unauthorized\r\n"
7220 "WWW-Authenticate: Mock realm=server\r\n"
7221 "Content-Type: text/html; charset=iso-8859-1\r\n"
7222 "Content-Length: 14\r\n\r\n"
7223 "Unauthorized\r\n");
7224 const MockRead kProxyChallenge(
7225 "HTTP/1.1 407 Unauthorized\r\n"
7226 "Proxy-Authenticate: Mock realm=proxy\r\n"
7227 "Proxy-Connection: close\r\n"
7228 "Content-Type: text/html; charset=iso-8859-1\r\n"
7229 "Content-Length: 14\r\n\r\n"
7230 "Unauthorized\r\n");
7231 const MockRead kProxyConnected(
7232 "HTTP/1.1 200 Connection Established\r\n\r\n");
7233
7234 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7235 // no constructors, but the C++ compiler on Windows warns about
7236 // unspecified data in compound literals. So, moved to using constructors,
7237 // and TestRound's created with the default constructor should not be used.
7238 struct TestRound {
7239 TestRound()
7240 : expected_rv(ERR_UNEXPECTED),
7241 extra_write(NULL),
7242 extra_read(NULL) {
7243 }
7244 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7245 int expected_rv_arg)
7246 : write(write_arg),
7247 read(read_arg),
7248 expected_rv(expected_rv_arg),
7249 extra_write(NULL),
7250 extra_read(NULL) {
7251 }
7252 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7253 int expected_rv_arg, const MockWrite* extra_write_arg,
7254 const MockWrite* extra_read_arg)
7255 : write(write_arg),
7256 read(read_arg),
7257 expected_rv(expected_rv_arg),
7258 extra_write(extra_write_arg),
7259 extra_read(extra_read_arg) {
7260 }
7261 MockWrite write;
7262 MockRead read;
7263 int expected_rv;
7264 const MockWrite* extra_write;
7265 const MockRead* extra_read;
7266 };
7267
7268 static const int kNoSSL = 500;
7269
7270 struct TestConfig {
7271 const char* proxy_url;
7272 AuthTiming proxy_auth_timing;
7273 int proxy_auth_rv;
7274 const char* server_url;
7275 AuthTiming server_auth_timing;
7276 int server_auth_rv;
7277 int num_auth_rounds;
7278 int first_ssl_round;
7279 TestRound rounds[3];
7280 } test_configs[] = {
7281 // Non-authenticating HTTP server with a direct connection.
7282 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7283 { TestRound(kGet, kSuccess, OK)}},
7284 // Authenticating HTTP server with a direct connection.
7285 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7286 { TestRound(kGet, kServerChallenge, OK),
7287 TestRound(kGetAuth, kSuccess, OK)}},
7288 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7289 { TestRound(kGet, kServerChallenge, OK),
7290 TestRound(kGetAuth, kFailure, kAuthErr)}},
7291 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7292 { TestRound(kGet, kServerChallenge, OK),
7293 TestRound(kGetAuth, kSuccess, OK)}},
7294 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7295 { TestRound(kGet, kServerChallenge, OK),
7296 TestRound(kGetAuth, kFailure, kAuthErr)}},
7297 // Non-authenticating HTTP server through a non-authenticating proxy.
7298 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7299 { TestRound(kGetProxy, kSuccess, OK)}},
7300 // Authenticating HTTP server through a non-authenticating proxy.
7301 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7302 { TestRound(kGetProxy, kServerChallenge, OK),
7303 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7304 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7305 { TestRound(kGetProxy, kServerChallenge, OK),
7306 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7307 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7308 { TestRound(kGetProxy, kServerChallenge, OK),
7309 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7310 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7311 { TestRound(kGetProxy, kServerChallenge, OK),
7312 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7313 // Non-authenticating HTTP server through an authenticating proxy.
7314 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7315 { TestRound(kGetProxy, kProxyChallenge, OK),
7316 TestRound(kGetProxyAuth, kSuccess, OK)}},
7317 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7318 { TestRound(kGetProxy, kProxyChallenge, OK),
7319 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7320 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7321 { TestRound(kGetProxy, kProxyChallenge, OK),
7322 TestRound(kGetProxyAuth, kSuccess, OK)}},
7323 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7324 { TestRound(kGetProxy, kProxyChallenge, OK),
7325 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7326 // Authenticating HTTP server through an authenticating proxy.
7327 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7328 { TestRound(kGetProxy, kProxyChallenge, OK),
7329 TestRound(kGetProxyAuth, kServerChallenge, OK),
7330 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7331 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7332 { TestRound(kGetProxy, kProxyChallenge, OK),
7333 TestRound(kGetProxyAuth, kServerChallenge, OK),
7334 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7335 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7336 { TestRound(kGetProxy, kProxyChallenge, OK),
7337 TestRound(kGetProxyAuth, kServerChallenge, OK),
7338 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7339 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7340 { TestRound(kGetProxy, kProxyChallenge, OK),
7341 TestRound(kGetProxyAuth, kServerChallenge, OK),
7342 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7343 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7344 { TestRound(kGetProxy, kProxyChallenge, OK),
7345 TestRound(kGetProxyAuth, kServerChallenge, OK),
7346 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7347 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7348 { TestRound(kGetProxy, kProxyChallenge, OK),
7349 TestRound(kGetProxyAuth, kServerChallenge, OK),
7350 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7351 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7352 { TestRound(kGetProxy, kProxyChallenge, OK),
7353 TestRound(kGetProxyAuth, kServerChallenge, OK),
7354 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7355 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7356 { TestRound(kGetProxy, kProxyChallenge, OK),
7357 TestRound(kGetProxyAuth, kServerChallenge, OK),
7358 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7359 // Non-authenticating HTTPS server with a direct connection.
7360 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7361 { TestRound(kGet, kSuccess, OK)}},
7362 // Authenticating HTTPS server with a direct connection.
7363 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7364 { TestRound(kGet, kServerChallenge, OK),
7365 TestRound(kGetAuth, kSuccess, OK)}},
7366 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7367 { TestRound(kGet, kServerChallenge, OK),
7368 TestRound(kGetAuth, kFailure, kAuthErr)}},
7369 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7370 { TestRound(kGet, kServerChallenge, OK),
7371 TestRound(kGetAuth, kSuccess, OK)}},
7372 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7373 { TestRound(kGet, kServerChallenge, OK),
7374 TestRound(kGetAuth, kFailure, kAuthErr)}},
7375 // Non-authenticating HTTPS server with a non-authenticating proxy.
7376 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7377 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7378 // Authenticating HTTPS server through a non-authenticating proxy.
7379 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7380 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7381 TestRound(kGetAuth, kSuccess, OK)}},
7382 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7383 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7384 TestRound(kGetAuth, kFailure, kAuthErr)}},
7385 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7386 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7387 TestRound(kGetAuth, kSuccess, OK)}},
7388 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7389 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7390 TestRound(kGetAuth, kFailure, kAuthErr)}},
7391 // Non-Authenticating HTTPS server through an authenticating proxy.
7392 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7393 { TestRound(kConnect, kProxyChallenge, OK),
7394 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7395 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7396 { TestRound(kConnect, kProxyChallenge, OK),
7397 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7398 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7399 { TestRound(kConnect, kProxyChallenge, OK),
7400 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7401 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7402 { TestRound(kConnect, kProxyChallenge, OK),
7403 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7404 // Authenticating HTTPS server through an authenticating proxy.
7405 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7406 { TestRound(kConnect, kProxyChallenge, OK),
7407 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7408 &kGet, &kServerChallenge),
7409 TestRound(kGetAuth, kSuccess, OK)}},
7410 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7411 { TestRound(kConnect, kProxyChallenge, OK),
7412 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7413 &kGet, &kServerChallenge),
7414 TestRound(kGetAuth, kFailure, kAuthErr)}},
7415 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7416 { TestRound(kConnect, kProxyChallenge, OK),
7417 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7418 &kGet, &kServerChallenge),
7419 TestRound(kGetAuth, kSuccess, OK)}},
7420 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7421 { TestRound(kConnect, kProxyChallenge, OK),
7422 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7423 &kGet, &kServerChallenge),
7424 TestRound(kGetAuth, kFailure, kAuthErr)}},
7425 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7426 { TestRound(kConnect, kProxyChallenge, OK),
7427 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7428 &kGet, &kServerChallenge),
7429 TestRound(kGetAuth, kSuccess, OK)}},
7430 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7431 { TestRound(kConnect, kProxyChallenge, OK),
7432 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7433 &kGet, &kServerChallenge),
7434 TestRound(kGetAuth, kFailure, kAuthErr)}},
7435 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7436 { TestRound(kConnect, kProxyChallenge, OK),
7437 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7438 &kGet, &kServerChallenge),
7439 TestRound(kGetAuth, kSuccess, OK)}},
7440 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7441 { TestRound(kConnect, kProxyChallenge, OK),
7442 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7443 &kGet, &kServerChallenge),
7444 TestRound(kGetAuth, kFailure, kAuthErr)}},
7445 };
7446
7447 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:007448 HttpAuthHandlerMock::Factory* auth_factory(
7449 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:157450 session_deps.http_auth_handler_factory.reset(auth_factory);
7451
7452 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
7453 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267454
7455 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157456 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007457 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157458 std::string auth_challenge = "Mock realm=proxy";
7459 GURL origin(test_config.proxy_url);
7460 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7461 auth_challenge.end());
7462 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7463 origin, BoundNetLog());
7464 auth_handler->SetGenerateExpectation(
7465 test_config.proxy_auth_timing == AUTH_ASYNC,
7466 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:157467 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7468 }
7469 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007470 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157471 std::string auth_challenge = "Mock realm=server";
7472 GURL origin(test_config.server_url);
7473 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7474 auth_challenge.end());
7475 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7476 origin, BoundNetLog());
7477 auth_handler->SetGenerateExpectation(
7478 test_config.server_auth_timing == AUTH_ASYNC,
7479 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:157480 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7481 }
7482 if (test_config.proxy_url) {
[email protected]6104ea5d2011-04-27 21:37:127483 session_deps.proxy_service.reset(
7484 ProxyService::CreateFixed(test_config.proxy_url));
[email protected]044de0642010-06-17 10:42:157485 } else {
[email protected]6104ea5d2011-04-27 21:37:127486 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]044de0642010-06-17 10:42:157487 }
7488
7489 HttpRequestInfo request;
7490 request.method = "GET";
7491 request.url = GURL(test_config.server_url);
7492 request.load_flags = 0;
7493
[email protected]0b0bf032010-09-21 18:08:507494 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7495 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157496
7497 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7498 const TestRound& read_write_round = test_config.rounds[round];
7499
7500 // Set up expected reads and writes.
7501 MockRead reads[2];
7502 reads[0] = read_write_round.read;
7503 size_t length_reads = 1;
7504 if (read_write_round.extra_read) {
7505 reads[1] = *read_write_round.extra_read;
7506 length_reads = 2;
7507 }
7508
7509 MockWrite writes[2];
7510 writes[0] = read_write_round.write;
7511 size_t length_writes = 1;
7512 if (read_write_round.extra_write) {
7513 writes[1] = *read_write_round.extra_write;
7514 length_writes = 2;
7515 }
7516 StaticSocketDataProvider data_provider(
7517 reads, length_reads, writes, length_writes);
7518 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7519
7520 // Add an SSL sequence if necessary.
7521 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7522 if (round >= test_config.first_ssl_round)
7523 session_deps.socket_factory.AddSSLSocketDataProvider(
7524 &ssl_socket_data_provider);
7525
7526 // Start or restart the transaction.
7527 TestCompletionCallback callback;
7528 int rv;
7529 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:507530 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:157531 } else {
[email protected]0b0bf032010-09-21 18:08:507532 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:157533 }
7534 if (rv == ERR_IO_PENDING)
7535 rv = callback.WaitForResult();
7536
7537 // Compare results with expected data.
7538 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507539 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157540 if (read_write_round.expected_rv == OK) {
7541 EXPECT_FALSE(response == NULL);
7542 } else {
7543 EXPECT_TRUE(response == NULL);
7544 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7545 continue;
7546 }
7547 if (round + 1 < test_config.num_auth_rounds) {
7548 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7549 } else {
7550 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7551 }
7552 }
[email protected]e5ae96a2010-04-14 20:12:457553 }
7554}
7555
[email protected]c871bce92010-07-15 21:51:147556TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7557 // Do multi-round authentication and make sure it works correctly.
7558 SessionDependencies session_deps;
7559 HttpAuthHandlerMock::Factory* auth_factory(
7560 new HttpAuthHandlerMock::Factory());
7561 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]6104ea5d2011-04-27 21:37:127562 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]c871bce92010-07-15 21:51:147563 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7564 session_deps.host_resolver->set_synchronous_mode(true);
7565
7566 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7567 auth_handler->set_connection_based(true);
7568 std::string auth_challenge = "Mock realm=server";
7569 GURL origin("http://www.example.com");
7570 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7571 auth_challenge.end());
7572 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7573 origin, BoundNetLog());
7574 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7575
[email protected]c871bce92010-07-15 21:51:147576 int rv = OK;
7577 const HttpResponseInfo* response = NULL;
7578 HttpRequestInfo request;
7579 request.method = "GET";
7580 request.url = origin;
7581 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277582
7583 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]7ef4cbbb2011-02-06 11:19:107584
7585 // Use a TCP Socket Pool with only one connection per group. This is used
7586 // to validate that the TCP socket is not released to the pool between
7587 // each round of multi-round authentication.
7588 HttpNetworkSessionPeer session_peer(session);
[email protected]ab739042011-04-07 15:22:287589 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7590 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:107591 50, // Max sockets for pool
7592 1, // Max sockets per group
[email protected]ab739042011-04-07 15:22:287593 &transport_pool_histograms,
[email protected]7ef4cbbb2011-02-06 11:19:107594 session_deps.host_resolver.get(),
7595 &session_deps.socket_factory,
7596 session_deps.net_log);
[email protected]ab739042011-04-07 15:22:287597 session_peer.SetTransportSocketPool(transport_pool);
[email protected]7ef4cbbb2011-02-06 11:19:107598
[email protected]cb9bf6ca2011-01-28 13:15:277599 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c871bce92010-07-15 21:51:147600 TestCompletionCallback callback;
7601
7602 const MockWrite kGet(
7603 "GET / HTTP/1.1\r\n"
7604 "Host: www.example.com\r\n"
7605 "Connection: keep-alive\r\n\r\n");
7606 const MockWrite kGetAuth(
7607 "GET / HTTP/1.1\r\n"
7608 "Host: www.example.com\r\n"
7609 "Connection: keep-alive\r\n"
7610 "Authorization: auth_token\r\n\r\n");
7611
7612 const MockRead kServerChallenge(
7613 "HTTP/1.1 401 Unauthorized\r\n"
7614 "WWW-Authenticate: Mock realm=server\r\n"
7615 "Content-Type: text/html; charset=iso-8859-1\r\n"
7616 "Content-Length: 14\r\n\r\n"
7617 "Unauthorized\r\n");
7618 const MockRead kSuccess(
7619 "HTTP/1.1 200 OK\r\n"
7620 "Content-Type: text/html; charset=iso-8859-1\r\n"
7621 "Content-Length: 3\r\n\r\n"
7622 "Yes");
7623
7624 MockWrite writes[] = {
7625 // First round
7626 kGet,
7627 // Second round
7628 kGetAuth,
7629 // Third round
7630 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307631 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:107632 kGetAuth,
7633 // Competing request
7634 kGet,
[email protected]c871bce92010-07-15 21:51:147635 };
7636 MockRead reads[] = {
7637 // First round
7638 kServerChallenge,
7639 // Second round
7640 kServerChallenge,
7641 // Third round
[email protected]eca50e122010-09-11 14:03:307642 kServerChallenge,
7643 // Fourth round
[email protected]c871bce92010-07-15 21:51:147644 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:107645 // Competing response
7646 kSuccess,
[email protected]c871bce92010-07-15 21:51:147647 };
7648 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7649 writes, arraysize(writes));
7650 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7651
[email protected]7ef4cbbb2011-02-06 11:19:107652 const char* const kSocketGroup = "www.example.com:80";
7653
7654 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:147655 auth_handler->SetGenerateExpectation(false, OK);
7656 rv = trans->Start(&request, &callback, BoundNetLog());
7657 if (rv == ERR_IO_PENDING)
7658 rv = callback.WaitForResult();
7659 EXPECT_EQ(OK, rv);
7660 response = trans->GetResponseInfo();
7661 ASSERT_FALSE(response == NULL);
7662 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287663 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147664
[email protected]7ef4cbbb2011-02-06 11:19:107665 // In between rounds, another request comes in for the same domain.
7666 // It should not be able to grab the TCP socket that trans has already
7667 // claimed.
7668 scoped_ptr<HttpTransaction> trans_compete(
7669 new HttpNetworkTransaction(session));
7670 TestCompletionCallback callback_compete;
7671 rv = trans_compete->Start(&request, &callback_compete, BoundNetLog());
7672 EXPECT_EQ(ERR_IO_PENDING, rv);
7673 // callback_compete.WaitForResult at this point would stall forever,
7674 // since the HttpNetworkTransaction does not release the request back to
7675 // the pool until after authentication completes.
7676
7677 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:147678 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447679 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:147680 if (rv == ERR_IO_PENDING)
7681 rv = callback.WaitForResult();
7682 EXPECT_EQ(OK, rv);
7683 response = trans->GetResponseInfo();
7684 ASSERT_FALSE(response == NULL);
7685 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287686 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147687
[email protected]7ef4cbbb2011-02-06 11:19:107688 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:147689 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447690 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:147691 if (rv == ERR_IO_PENDING)
7692 rv = callback.WaitForResult();
7693 EXPECT_EQ(OK, rv);
7694 response = trans->GetResponseInfo();
7695 ASSERT_FALSE(response == NULL);
7696 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287697 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:307698
[email protected]7ef4cbbb2011-02-06 11:19:107699 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:307700 auth_handler->SetGenerateExpectation(false, OK);
7701 rv = trans->RestartWithAuth(string16(), string16(), &callback);
7702 if (rv == ERR_IO_PENDING)
7703 rv = callback.WaitForResult();
7704 EXPECT_EQ(OK, rv);
7705 response = trans->GetResponseInfo();
7706 ASSERT_FALSE(response == NULL);
7707 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287708 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107709
7710 // Read the body since the fourth round was successful. This will also
7711 // release the socket back to the pool.
7712 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
7713 rv = trans->Read(io_buf, io_buf->size(), &callback);
7714 if (rv == ERR_IO_PENDING)
7715 rv = callback.WaitForResult();
7716 EXPECT_EQ(3, rv);
7717 rv = trans->Read(io_buf, io_buf->size(), &callback);
7718 EXPECT_EQ(0, rv);
7719 // There are still 0 idle sockets, since the trans_compete transaction
7720 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:287721 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107722
7723 // The competing request can now finish. Wait for the headers and then
7724 // read the body.
7725 rv = callback_compete.WaitForResult();
7726 EXPECT_EQ(OK, rv);
7727 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7728 if (rv == ERR_IO_PENDING)
7729 rv = callback.WaitForResult();
7730 EXPECT_EQ(3, rv);
7731 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7732 EXPECT_EQ(0, rv);
7733
7734 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:287735 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147736}
7737
[email protected]aeaca1f2010-04-20 22:05:217738class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7739 public:
[email protected]06650c52010-06-03 00:49:177740 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217741 : fail_all_(fail_all) {
7742 }
7743
7744 virtual MockRead GetNextRead() {
7745 if (fail_all_)
7746 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7747
7748 return MockRead(false /* async */,
7749 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7750 }
7751
7752 virtual MockWriteResult OnWrite(const std::string& data) {
7753 return MockWriteResult(false /* async */, data.size());
7754 }
7755
7756 void Reset() {
7757 }
7758
7759 private:
7760 const bool fail_all_;
7761};
7762
7763// Test that we restart a connection when we see a decompression failure from
7764// the peer during the handshake. (In the real world we'll restart with SSLv3
7765// and we won't offer DEFLATE in that case.)
7766TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7767 HttpRequestInfo request;
7768 request.method = "GET";
7769 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7770 request.load_flags = 0;
7771
7772 SessionDependencies session_deps;
7773 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7774 false /* fail all reads */);
7775 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7776 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117777 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217778 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7779 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7780 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7781 session_deps.socket_factory.AddSSLSocketDataProvider(
7782 &ssl_socket_data_provider1);
7783 session_deps.socket_factory.AddSSLSocketDataProvider(
7784 &ssl_socket_data_provider2);
7785
[email protected]e60e47a2010-07-14 03:37:187786 // Work around http://crbug.com/37454
7787 StaticSocketDataProvider bug37454_connection;
7788 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7789 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7790
[email protected]aeaca1f2010-04-20 22:05:217791 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7792 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7793 TestCompletionCallback callback;
7794
[email protected]5a1d7ca2010-04-28 20:12:277795 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217796 EXPECT_EQ(ERR_IO_PENDING, rv);
7797 EXPECT_EQ(OK, callback.WaitForResult());
7798
7799 const HttpResponseInfo* response = trans->GetResponseInfo();
7800 ASSERT_TRUE(response != NULL);
7801 ASSERT_TRUE(response->headers != NULL);
7802 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7803
7804 std::string response_data;
7805 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7806 EXPECT_EQ("ok.", response_data);
7807}
7808
7809// Test that we restart a connection if we get a decompression failure from the
7810// peer while reading the first bytes from the connection. This occurs when the
7811// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7812// in the handshake.
7813TEST_F(HttpNetworkTransactionTest,
7814 RestartAfterTLSDecompressionFailureWithFalseStart) {
7815 HttpRequestInfo request;
7816 request.method = "GET";
7817 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7818 request.load_flags = 0;
7819
7820 SessionDependencies session_deps;
7821 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7822 true /* fail all reads */);
7823 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7824 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7825 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7826 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7827 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7828 session_deps.socket_factory.AddSSLSocketDataProvider(
7829 &ssl_socket_data_provider1);
7830 session_deps.socket_factory.AddSSLSocketDataProvider(
7831 &ssl_socket_data_provider2);
7832
7833 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7834 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7835 TestCompletionCallback callback;
7836
[email protected]5a1d7ca2010-04-28 20:12:277837 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217838 EXPECT_EQ(ERR_IO_PENDING, rv);
7839 EXPECT_EQ(OK, callback.WaitForResult());
7840
7841 const HttpResponseInfo* response = trans->GetResponseInfo();
7842 ASSERT_TRUE(response != NULL);
7843 ASSERT_TRUE(response->headers != NULL);
7844 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7845
7846 std::string response_data;
7847 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7848 EXPECT_EQ("ok.", response_data);
7849}
7850
[email protected]65041fa2010-05-21 06:56:537851// This tests the case that a request is issued via http instead of spdy after
7852// npn is negotiated.
7853TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387854 HttpStreamFactory::set_use_alternate_protocols(true);
7855 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537856 SessionDependencies session_deps;
7857 HttpRequestInfo request;
7858 request.method = "GET";
7859 request.url = GURL("https://www.google.com/");
7860 request.load_flags = 0;
7861
7862 MockWrite data_writes[] = {
7863 MockWrite("GET / HTTP/1.1\r\n"
7864 "Host: www.google.com\r\n"
7865 "Connection: keep-alive\r\n\r\n"),
7866 };
7867
7868 MockRead data_reads[] = {
7869 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357870 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537871 MockRead("hello world"),
7872 MockRead(false, OK),
7873 };
7874
7875 SSLSocketDataProvider ssl(true, OK);
7876 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7877 ssl.next_proto = "http/1.1";
7878
7879 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7880
7881 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7882 data_writes, arraysize(data_writes));
7883 session_deps.socket_factory.AddSocketDataProvider(&data);
7884
7885 TestCompletionCallback callback;
7886
7887 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7888 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7889
7890 int rv = trans->Start(&request, &callback, BoundNetLog());
7891
7892 EXPECT_EQ(ERR_IO_PENDING, rv);
7893 EXPECT_EQ(OK, callback.WaitForResult());
7894
7895 const HttpResponseInfo* response = trans->GetResponseInfo();
7896 ASSERT_TRUE(response != NULL);
7897 ASSERT_TRUE(response->headers != NULL);
7898 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7899
7900 std::string response_data;
7901 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7902 EXPECT_EQ("hello world", response_data);
7903
7904 EXPECT_FALSE(response->was_fetched_via_spdy);
7905 EXPECT_TRUE(response->was_npn_negotiated);
7906
[email protected]8e6441ca2010-08-19 05:56:387907 HttpStreamFactory::set_next_protos("");
7908 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537909}
[email protected]26ef6582010-06-24 02:30:477910
7911TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7912 // Simulate the SSL handshake completing with an NPN negotiation
7913 // followed by an immediate server closing of the socket.
7914 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387915 HttpStreamFactory::set_use_alternate_protocols(true);
7916 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477917 SessionDependencies session_deps;
7918
7919 HttpRequestInfo request;
7920 request.method = "GET";
7921 request.url = GURL("https://www.google.com/");
7922 request.load_flags = 0;
7923
7924 SSLSocketDataProvider ssl(true, OK);
7925 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357926 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477927 ssl.was_npn_negotiated = true;
7928 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7929
[email protected]2bd93022010-07-17 00:58:447930 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137931 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477932
7933 MockRead spdy_reads[] = {
7934 MockRead(false, 0, 0) // Not async - return 0 immediately.
7935 };
7936
7937 scoped_refptr<DelayedSocketData> spdy_data(
7938 new DelayedSocketData(
7939 0, // don't wait in this case, immediate hangup.
7940 spdy_reads, arraysize(spdy_reads),
7941 spdy_writes, arraysize(spdy_writes)));
7942 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7943
7944 TestCompletionCallback callback;
7945
7946 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7947 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7948
7949 int rv = trans->Start(&request, &callback, BoundNetLog());
7950 EXPECT_EQ(ERR_IO_PENDING, rv);
7951 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7952
[email protected]8e6441ca2010-08-19 05:56:387953 HttpStreamFactory::set_next_protos("");
7954 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477955}
[email protected]65d34382010-07-01 18:12:267956
[email protected]f45c1ee2010-08-03 00:54:307957TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7958 // This test ensures that the URL passed into the proxy is upgraded
7959 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387960 HttpStreamFactory::set_use_alternate_protocols(true);
7961 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307962 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7963
[email protected]81cdfcd2010-10-16 00:49:007964 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307965 HttpAuthHandlerMock::Factory* auth_factory =
7966 new HttpAuthHandlerMock::Factory();
7967 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7968 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7969 auth_factory->set_do_init_from_challenge(true);
7970 session_deps.http_auth_handler_factory.reset(auth_factory);
7971
7972 HttpRequestInfo request;
7973 request.method = "GET";
7974 request.url = GURL("http://www.google.com");
7975 request.load_flags = 0;
7976
7977 // First round goes unauthenticated through the proxy.
7978 MockWrite data_writes_1[] = {
7979 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7980 "Host: www.google.com\r\n"
7981 "Proxy-Connection: keep-alive\r\n"
7982 "\r\n"),
7983 };
7984 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597985 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307986 MockRead("HTTP/1.1 200 OK\r\n"
7987 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7988 "Proxy-Connection: close\r\n"
7989 "\r\n"),
7990 };
7991 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7992 data_writes_1, arraysize(data_writes_1));
7993
7994 // Second round tries to tunnel to www.google.com due to the
7995 // Alternate-Protocol announcement in the first round. It fails due
7996 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597997 // After the failure, a tunnel is established to www.google.com using
7998 // Proxy-Authorization headers. There is then a SPDY request round.
7999 //
8000 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
8001 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
8002 // does a Disconnect and Connect on the same socket, rather than trying
8003 // to obtain a new one.
8004 //
8005 // NOTE: Originally, the proxy response to the second CONNECT request
8006 // simply returned another 407 so the unit test could skip the SSL connection
8007 // establishment and SPDY framing issues. Alas, the
8008 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:308009 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:598010
[email protected]f45c1ee2010-08-03 00:54:308011 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
8012 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8013 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8014
[email protected]394816e92010-08-03 07:38:598015 MockWrite data_writes_2[] = {
8016 // First connection attempt without Proxy-Authorization.
8017 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8018 "Host: www.google.com\r\n"
8019 "Proxy-Connection: keep-alive\r\n"
8020 "\r\n"),
8021
8022 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:308023 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8024 "Host: www.google.com\r\n"
8025 "Proxy-Connection: keep-alive\r\n"
8026 "Proxy-Authorization: auth_token\r\n"
8027 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:308028
[email protected]394816e92010-08-03 07:38:598029 // SPDY request
8030 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:308031 };
[email protected]394816e92010-08-03 07:38:598032 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
8033 "Proxy-Authenticate: Mock\r\n"
8034 "Proxy-Connection: close\r\n"
8035 "\r\n");
8036 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8037 MockRead data_reads_2[] = {
8038 // First connection attempt fails
8039 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
8040 MockRead(true, kRejectConnectResponse,
8041 arraysize(kRejectConnectResponse) - 1, 1),
8042
8043 // Second connection attempt passes
8044 MockRead(true, kAcceptConnectResponse,
8045 arraysize(kAcceptConnectResponse) -1, 4),
8046
8047 // SPDY response
8048 CreateMockRead(*resp.get(), 6),
8049 CreateMockRead(*data.get(), 6),
8050 MockRead(true, 0, 0, 6),
8051 };
8052 scoped_refptr<OrderedSocketData> data_2(
8053 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8054 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:308055
8056 SSLSocketDataProvider ssl(true, OK);
8057 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8058 ssl.next_proto = "spdy/2";
8059 ssl.was_npn_negotiated = true;
8060
[email protected]2d6728692011-03-12 01:39:558061 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
8062 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8063 NULL, 0, NULL, 0);
8064 hanging_non_alternate_protocol_socket.set_connect_data(
8065 never_finishing_connect);
8066
[email protected]f45c1ee2010-08-03 00:54:308067 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:598068 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:308069 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:558070 session_deps.socket_factory.AddSocketDataProvider(
8071 &hanging_non_alternate_protocol_socket);
[email protected]f45c1ee2010-08-03 00:54:308072 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8073
8074 // First round should work and provide the Alternate-Protocol state.
8075 TestCompletionCallback callback_1;
8076 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
8077 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
8078 EXPECT_EQ(ERR_IO_PENDING, rv);
8079 EXPECT_EQ(OK, callback_1.WaitForResult());
8080
8081 // Second round should attempt a tunnel connect and get an auth challenge.
8082 TestCompletionCallback callback_2;
8083 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
8084 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
8085 EXPECT_EQ(ERR_IO_PENDING, rv);
8086 EXPECT_EQ(OK, callback_2.WaitForResult());
8087 const HttpResponseInfo* response = trans_2->GetResponseInfo();
8088 ASSERT_FALSE(response == NULL);
8089 ASSERT_FALSE(response->auth_challenge.get() == NULL);
8090
8091 // Restart with auth. Tunnel should work and response received.
8092 TestCompletionCallback callback_3;
8093 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
8094 EXPECT_EQ(ERR_IO_PENDING, rv);
8095 EXPECT_EQ(OK, callback_3.WaitForResult());
8096
8097 // After all that work, these two lines (or actually, just the scheme) are
8098 // what this test is all about. Make sure it happens correctly.
8099 const GURL& request_url = auth_handler->request_url();
8100 EXPECT_EQ("https", request_url.scheme());
8101 EXPECT_EQ("www.google.com", request_url.host());
8102
[email protected]8e6441ca2010-08-19 05:56:388103 HttpStreamFactory::set_next_protos("");
8104 HttpStreamFactory::set_use_alternate_protocols(false);
8105}
8106
8107// Test that if we cancel the transaction as the connection is completing, that
8108// everything tears down correctly.
8109TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8110 // Setup everything about the connection to complete synchronously, so that
8111 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8112 // for is the callback from the HttpStreamRequest.
8113 // Then cancel the transaction.
8114 // Verify that we don't crash.
8115 MockConnect mock_connect(false, OK);
8116 MockRead data_reads[] = {
8117 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
8118 MockRead(false, "hello world"),
8119 MockRead(false, OK),
8120 };
8121
[email protected]8e6441ca2010-08-19 05:56:388122 HttpRequestInfo request;
8123 request.method = "GET";
8124 request.url = GURL("http://www.google.com/");
8125 request.load_flags = 0;
8126
[email protected]cb9bf6ca2011-01-28 13:15:278127 SessionDependencies session_deps;
8128 session_deps.host_resolver->set_synchronous_mode(true);
8129 scoped_ptr<HttpTransaction> trans(
8130 new HttpNetworkTransaction(CreateSession(&session_deps)));
8131
[email protected]8e6441ca2010-08-19 05:56:388132 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8133 data.set_connect_data(mock_connect);
8134 session_deps.socket_factory.AddSocketDataProvider(&data);
8135
8136 TestCompletionCallback callback;
8137
8138 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8139 int rv = trans->Start(&request, &callback, log.bound());
8140 EXPECT_EQ(ERR_IO_PENDING, rv);
8141 trans.reset(); // Cancel the transaction here.
8142
8143 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:308144}
8145
[email protected]76a505b2010-08-25 06:23:008146// Test a basic GET request through a proxy.
8147TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:008148 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008149 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8150 session_deps.net_log = log.bound().net_log();
8151 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8152
[email protected]76a505b2010-08-25 06:23:008153 HttpRequestInfo request;
8154 request.method = "GET";
8155 request.url = GURL("http://www.google.com/");
8156
8157 MockWrite data_writes1[] = {
8158 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8159 "Host: www.google.com\r\n"
8160 "Proxy-Connection: keep-alive\r\n\r\n"),
8161 };
8162
8163 MockRead data_reads1[] = {
8164 MockRead("HTTP/1.1 200 OK\r\n"),
8165 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8166 MockRead("Content-Length: 100\r\n\r\n"),
8167 MockRead(false, OK),
8168 };
8169
8170 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8171 data_writes1, arraysize(data_writes1));
8172 session_deps.socket_factory.AddSocketDataProvider(&data1);
8173
8174 TestCompletionCallback callback1;
8175
[email protected]0b0bf032010-09-21 18:08:508176 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8177
[email protected]76a505b2010-08-25 06:23:008178 int rv = trans->Start(&request, &callback1, log.bound());
8179 EXPECT_EQ(ERR_IO_PENDING, rv);
8180
8181 rv = callback1.WaitForResult();
8182 EXPECT_EQ(OK, rv);
8183
8184 const HttpResponseInfo* response = trans->GetResponseInfo();
8185 ASSERT_FALSE(response == NULL);
8186
8187 EXPECT_TRUE(response->headers->IsKeepAlive());
8188 EXPECT_EQ(200, response->headers->response_code());
8189 EXPECT_EQ(100, response->headers->GetContentLength());
8190 EXPECT_TRUE(response->was_fetched_via_proxy);
8191 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8192}
8193
8194// Test a basic HTTPS GET request through a proxy.
8195TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:008196 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008197 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8198 session_deps.net_log = log.bound().net_log();
8199 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8200
[email protected]76a505b2010-08-25 06:23:008201 HttpRequestInfo request;
8202 request.method = "GET";
8203 request.url = GURL("https://www.google.com/");
8204
8205 // Since we have proxy, should try to establish tunnel.
8206 MockWrite data_writes1[] = {
8207 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8208 "Host: www.google.com\r\n"
8209 "Proxy-Connection: keep-alive\r\n\r\n"),
8210
8211 MockWrite("GET / HTTP/1.1\r\n"
8212 "Host: www.google.com\r\n"
8213 "Connection: keep-alive\r\n\r\n"),
8214 };
8215
8216 MockRead data_reads1[] = {
8217 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8218
8219 MockRead("HTTP/1.1 200 OK\r\n"),
8220 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8221 MockRead("Content-Length: 100\r\n\r\n"),
8222 MockRead(false, OK),
8223 };
8224
8225 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8226 data_writes1, arraysize(data_writes1));
8227 session_deps.socket_factory.AddSocketDataProvider(&data1);
8228 SSLSocketDataProvider ssl(true, OK);
8229 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8230
8231 TestCompletionCallback callback1;
8232
[email protected]0b0bf032010-09-21 18:08:508233 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8234
[email protected]76a505b2010-08-25 06:23:008235 int rv = trans->Start(&request, &callback1, log.bound());
8236 EXPECT_EQ(ERR_IO_PENDING, rv);
8237
8238 rv = callback1.WaitForResult();
8239 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:408240 net::CapturingNetLog::EntryList entries;
8241 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008242 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408243 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008244 NetLog::PHASE_NONE);
8245 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408246 entries, pos,
[email protected]76a505b2010-08-25 06:23:008247 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8248 NetLog::PHASE_NONE);
8249
8250 const HttpResponseInfo* response = trans->GetResponseInfo();
8251 ASSERT_FALSE(response == NULL);
8252
8253 EXPECT_TRUE(response->headers->IsKeepAlive());
8254 EXPECT_EQ(200, response->headers->response_code());
8255 EXPECT_EQ(100, response->headers->GetContentLength());
8256 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8257 EXPECT_TRUE(response->was_fetched_via_proxy);
8258}
8259
8260// Test a basic HTTPS GET request through a proxy, but the server hangs up
8261// while establishing the tunnel.
8262TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008263 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008264 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8265 session_deps.net_log = log.bound().net_log();
8266 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8267
[email protected]76a505b2010-08-25 06:23:008268 HttpRequestInfo request;
8269 request.method = "GET";
8270 request.url = GURL("https://www.google.com/");
8271
8272 // Since we have proxy, should try to establish tunnel.
8273 MockWrite data_writes1[] = {
8274 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8275 "Host: www.google.com\r\n"
8276 "Proxy-Connection: keep-alive\r\n\r\n"),
8277
8278 MockWrite("GET / HTTP/1.1\r\n"
8279 "Host: www.google.com\r\n"
8280 "Connection: keep-alive\r\n\r\n"),
8281 };
8282
8283 MockRead data_reads1[] = {
8284 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8285 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8286 MockRead(true, 0, 0), // EOF
8287 };
8288
8289 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8290 data_writes1, arraysize(data_writes1));
8291 session_deps.socket_factory.AddSocketDataProvider(&data1);
8292 SSLSocketDataProvider ssl(true, OK);
8293 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8294
8295 TestCompletionCallback callback1;
8296
[email protected]0b0bf032010-09-21 18:08:508297 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8298
[email protected]76a505b2010-08-25 06:23:008299 int rv = trans->Start(&request, &callback1, log.bound());
8300 EXPECT_EQ(ERR_IO_PENDING, rv);
8301
8302 rv = callback1.WaitForResult();
8303 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408304 net::CapturingNetLog::EntryList entries;
8305 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008306 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408307 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008308 NetLog::PHASE_NONE);
8309 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408310 entries, pos,
[email protected]76a505b2010-08-25 06:23:008311 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8312 NetLog::PHASE_NONE);
8313}
8314
[email protected]749eefa82010-09-13 22:14:038315// Test for crbug.com/55424.
8316TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8317 SessionDependencies session_deps;
8318
8319 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8320 "https://www.google.com", false, 1, LOWEST));
8321 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8322
8323 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8324 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8325 MockRead spdy_reads[] = {
8326 CreateMockRead(*resp),
8327 CreateMockRead(*data),
8328 MockRead(true, 0, 0),
8329 };
8330
8331 scoped_refptr<DelayedSocketData> spdy_data(
8332 new DelayedSocketData(
8333 1, // wait for one write to finish before reading.
8334 spdy_reads, arraysize(spdy_reads),
8335 spdy_writes, arraysize(spdy_writes)));
8336 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8337
8338 SSLSocketDataProvider ssl(true, OK);
8339 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8340 ssl.next_proto = "spdy/2";
8341 ssl.was_npn_negotiated = true;
8342 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8343
8344 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8345
8346 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388347 HostPortPair host_port_pair("www.google.com", 443);
8348 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038349 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:318350 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:288351 scoped_refptr<TransportSocketParams> transport_params(
8352 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
[email protected]02b0c342010-09-25 21:09:388353 TestCompletionCallback callback;
8354
8355 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8356 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:288357 connection->Init(host_port_pair.ToString(), transport_params,
8358 LOWEST, &callback,
8359 session->transport_socket_pool(), BoundNetLog()));
[email protected]02b0c342010-09-25 21:09:388360 EXPECT_EQ(OK, callback.WaitForResult());
8361 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038362
8363 HttpRequestInfo request;
8364 request.method = "GET";
8365 request.url = GURL("https://www.google.com/");
8366 request.load_flags = 0;
8367
8368 // This is the important line that marks this as a preconnect.
8369 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8370
8371 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8372
[email protected]749eefa82010-09-13 22:14:038373 int rv = trans->Start(&request, &callback, BoundNetLog());
8374 EXPECT_EQ(ERR_IO_PENDING, rv);
8375 EXPECT_EQ(OK, callback.WaitForResult());
8376}
8377
[email protected]73b8dd222010-11-11 19:55:248378// Given a net error, cause that error to be returned from the first Write()
8379// call and verify that the HttpTransaction fails with that error.
8380static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278381 net::HttpRequestInfo request_info;
8382 request_info.url = GURL("https://www.example.com/");
8383 request_info.method = "GET";
8384 request_info.load_flags = net::LOAD_NORMAL;
8385
[email protected]73b8dd222010-11-11 19:55:248386 SessionDependencies session_deps;
8387
8388 SSLSocketDataProvider ssl_data(async, OK);
8389 net::MockWrite data_writes[] = {
8390 net::MockWrite(async, error),
8391 };
8392 net::StaticSocketDataProvider data(NULL, 0,
8393 data_writes, arraysize(data_writes));
8394 session_deps.socket_factory.AddSocketDataProvider(&data);
8395 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8396
8397 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8398 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8399
[email protected]73b8dd222010-11-11 19:55:248400 TestCompletionCallback callback;
8401 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8402 if (rv == net::ERR_IO_PENDING)
8403 rv = callback.WaitForResult();
8404 ASSERT_EQ(error, rv);
8405}
8406
8407TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8408 // Just check a grab bag of cert errors.
8409 static const int kErrors[] = {
8410 ERR_CERT_COMMON_NAME_INVALID,
8411 ERR_CERT_AUTHORITY_INVALID,
8412 ERR_CERT_DATE_INVALID,
8413 };
8414 for (size_t i = 0; i < arraysize(kErrors); i++) {
8415 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8416 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8417 }
8418}
8419
[email protected]bd0b6772011-01-11 19:59:308420// Ensure that a client certificate is removed from the SSL client auth
8421// cache when:
8422// 1) No proxy is involved.
8423// 2) TLS False Start is disabled.
8424// 3) The initial TLS handshake requests a client certificate.
8425// 4) The client supplies an invalid/unacceptable certificate.
8426TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278427 net::HttpRequestInfo request_info;
8428 request_info.url = GURL("https://www.example.com/");
8429 request_info.method = "GET";
8430 request_info.load_flags = net::LOAD_NORMAL;
8431
[email protected]bd0b6772011-01-11 19:59:308432 SessionDependencies session_deps;
8433
8434 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8435 cert_request->host_and_port = "www.example.com:443";
8436
8437 // [ssl_]data1 contains the data for the first SSL handshake. When a
8438 // CertificateRequest is received for the first time, the handshake will
8439 // be aborted to allow the caller to provide a certificate.
8440 SSLSocketDataProvider ssl_data1(true /* async */,
8441 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8442 ssl_data1.cert_request_info = cert_request.get();
8443 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8444 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8445 session_deps.socket_factory.AddSocketDataProvider(&data1);
8446
8447 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8448 // False Start is not being used, the result of the SSL handshake will be
8449 // returned as part of the SSLClientSocket::Connect() call. This test
8450 // matches the result of a server sending a handshake_failure alert,
8451 // rather than a Finished message, because it requires a client
8452 // certificate and none was supplied.
8453 SSLSocketDataProvider ssl_data2(true /* async */,
8454 net::ERR_SSL_PROTOCOL_ERROR);
8455 ssl_data2.cert_request_info = cert_request.get();
8456 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8457 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8458 session_deps.socket_factory.AddSocketDataProvider(&data2);
8459
8460 // [ssl_]data3 contains the data for the third SSL handshake. When a
8461 // connection to a server fails during an SSL handshake,
8462 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8463 // connection was attempted with TLSv1. This is transparent to the caller
8464 // of the HttpNetworkTransaction. Because this test failure is due to
8465 // requiring a client certificate, this fallback handshake should also
8466 // fail.
8467 SSLSocketDataProvider ssl_data3(true /* async */,
8468 net::ERR_SSL_PROTOCOL_ERROR);
8469 ssl_data3.cert_request_info = cert_request.get();
8470 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8471 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8472 session_deps.socket_factory.AddSocketDataProvider(&data3);
8473
8474 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8475 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8476
[email protected]bd0b6772011-01-11 19:59:308477 // Begin the SSL handshake with the peer. This consumes ssl_data1.
8478 TestCompletionCallback callback;
8479 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8480 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8481
8482 // Complete the SSL handshake, which should abort due to requiring a
8483 // client certificate.
8484 rv = callback.WaitForResult();
8485 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8486
8487 // Indicate that no certificate should be supplied. From the perspective
8488 // of SSLClientCertCache, NULL is just as meaningful as a real
8489 // certificate, so this is the same as supply a
8490 // legitimate-but-unacceptable certificate.
8491 rv = trans->RestartWithCertificate(NULL, &callback);
8492 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8493
8494 // Ensure the certificate was added to the client auth cache before
8495 // allowing the connection to continue restarting.
8496 scoped_refptr<X509Certificate> client_cert;
8497 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8498 &client_cert));
8499 ASSERT_EQ(NULL, client_cert.get());
8500
8501 // Restart the handshake. This will consume ssl_data2, which fails, and
8502 // then consume ssl_data3, which should also fail. The result code is
8503 // checked against what ssl_data3 should return.
8504 rv = callback.WaitForResult();
8505 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8506
8507 // Ensure that the client certificate is removed from the cache on a
8508 // handshake failure.
8509 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8510 &client_cert));
8511}
8512
8513// Ensure that a client certificate is removed from the SSL client auth
8514// cache when:
8515// 1) No proxy is involved.
8516// 2) TLS False Start is enabled.
8517// 3) The initial TLS handshake requests a client certificate.
8518// 4) The client supplies an invalid/unacceptable certificate.
8519TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278520 net::HttpRequestInfo request_info;
8521 request_info.url = GURL("https://www.example.com/");
8522 request_info.method = "GET";
8523 request_info.load_flags = net::LOAD_NORMAL;
8524
[email protected]bd0b6772011-01-11 19:59:308525 SessionDependencies session_deps;
8526
8527 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8528 cert_request->host_and_port = "www.example.com:443";
8529
8530 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8531 // return successfully after reading up to the peer's Certificate message.
8532 // This is to allow the caller to call SSLClientSocket::Write(), which can
8533 // enqueue application data to be sent in the same packet as the
8534 // ChangeCipherSpec and Finished messages.
8535 // The actual handshake will be finished when SSLClientSocket::Read() is
8536 // called, which expects to process the peer's ChangeCipherSpec and
8537 // Finished messages. If there was an error negotiating with the peer,
8538 // such as due to the peer requiring a client certificate when none was
8539 // supplied, the alert sent by the peer won't be processed until Read() is
8540 // called.
8541
8542 // Like the non-False Start case, when a client certificate is requested by
8543 // the peer, the handshake is aborted during the Connect() call.
8544 // [ssl_]data1 represents the initial SSL handshake with the peer.
8545 SSLSocketDataProvider ssl_data1(true /* async */,
8546 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8547 ssl_data1.cert_request_info = cert_request.get();
8548 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8549 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8550 session_deps.socket_factory.AddSocketDataProvider(&data1);
8551
8552 // When a client certificate is supplied, Connect() will not be aborted
8553 // when the peer requests the certificate. Instead, the handshake will
8554 // artificially succeed, allowing the caller to write the HTTP request to
8555 // the socket. The handshake messages are not processed until Read() is
8556 // called, which then detects that the handshake was aborted, due to the
8557 // peer sending a handshake_failure because it requires a client
8558 // certificate.
8559 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8560 ssl_data2.cert_request_info = cert_request.get();
8561 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8562 net::MockRead data2_reads[] = {
8563 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8564 };
8565 net::StaticSocketDataProvider data2(
8566 data2_reads, arraysize(data2_reads), NULL, 0);
8567 session_deps.socket_factory.AddSocketDataProvider(&data2);
8568
8569 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8570 // the data for the SSL handshake once the TLSv1 connection falls back to
8571 // SSLv3. It has the same behaviour as [ssl_]data2.
8572 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8573 ssl_data3.cert_request_info = cert_request.get();
8574 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8575 net::StaticSocketDataProvider data3(
8576 data2_reads, arraysize(data2_reads), NULL, 0);
8577 session_deps.socket_factory.AddSocketDataProvider(&data3);
8578
8579 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8580 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8581
[email protected]bd0b6772011-01-11 19:59:308582 // Begin the initial SSL handshake.
8583 TestCompletionCallback callback;
8584 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8585 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8586
8587 // Complete the SSL handshake, which should abort due to requiring a
8588 // client certificate.
8589 rv = callback.WaitForResult();
8590 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8591
8592 // Indicate that no certificate should be supplied. From the perspective
8593 // of SSLClientCertCache, NULL is just as meaningful as a real
8594 // certificate, so this is the same as supply a
8595 // legitimate-but-unacceptable certificate.
8596 rv = trans->RestartWithCertificate(NULL, &callback);
8597 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8598
8599 // Ensure the certificate was added to the client auth cache before
8600 // allowing the connection to continue restarting.
8601 scoped_refptr<X509Certificate> client_cert;
8602 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8603 &client_cert));
8604 ASSERT_EQ(NULL, client_cert.get());
8605
8606
8607 // Restart the handshake. This will consume ssl_data2, which fails, and
8608 // then consume ssl_data3, which should also fail. The result code is
8609 // checked against what ssl_data3 should return.
8610 rv = callback.WaitForResult();
8611 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8612
8613 // Ensure that the client certificate is removed from the cache on a
8614 // handshake failure.
8615 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8616 &client_cert));
8617}
8618
[email protected]8c405132011-01-11 22:03:188619// Ensure that a client certificate is removed from the SSL client auth
8620// cache when:
8621// 1) An HTTPS proxy is involved.
8622// 3) The HTTPS proxy requests a client certificate.
8623// 4) The client supplies an invalid/unacceptable certificate for the
8624// proxy.
8625// The test is repeated twice, first for connecting to an HTTPS endpoint,
8626// then for connecting to an HTTP endpoint.
8627TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8628 SessionDependencies session_deps(
8629 ProxyService::CreateFixed("https://proxy:70"));
8630 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8631 session_deps.net_log = log.bound().net_log();
8632
8633 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8634 cert_request->host_and_port = "proxy:70";
8635
8636 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8637 // [ssl_]data[1-3]. Rather than represending the endpoint
8638 // (www.example.com:443), they represent failures with the HTTPS proxy
8639 // (proxy:70).
8640 SSLSocketDataProvider ssl_data1(true /* async */,
8641 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8642 ssl_data1.cert_request_info = cert_request.get();
8643 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8644 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8645 session_deps.socket_factory.AddSocketDataProvider(&data1);
8646
8647 SSLSocketDataProvider ssl_data2(true /* async */,
8648 net::ERR_SSL_PROTOCOL_ERROR);
8649 ssl_data2.cert_request_info = cert_request.get();
8650 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8651 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8652 session_deps.socket_factory.AddSocketDataProvider(&data2);
8653
8654 SSLSocketDataProvider ssl_data3(true /* async */,
8655 net::ERR_SSL_PROTOCOL_ERROR);
8656 ssl_data3.cert_request_info = cert_request.get();
8657 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8658 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8659 session_deps.socket_factory.AddSocketDataProvider(&data3);
8660
8661 net::HttpRequestInfo requests[2];
8662 requests[0].url = GURL("https://www.example.com/");
8663 requests[0].method = "GET";
8664 requests[0].load_flags = net::LOAD_NORMAL;
8665
8666 requests[1].url = GURL("http://www.example.com/");
8667 requests[1].method = "GET";
8668 requests[1].load_flags = net::LOAD_NORMAL;
8669
8670 for (size_t i = 0; i < arraysize(requests); ++i) {
8671 session_deps.socket_factory.ResetNextMockIndexes();
8672 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8673 scoped_ptr<HttpNetworkTransaction> trans(
8674 new HttpNetworkTransaction(session));
8675
8676 // Begin the SSL handshake with the proxy.
8677 TestCompletionCallback callback;
8678 int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
8679 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8680
8681 // Complete the SSL handshake, which should abort due to requiring a
8682 // client certificate.
8683 rv = callback.WaitForResult();
8684 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8685
8686 // Indicate that no certificate should be supplied. From the perspective
8687 // of SSLClientCertCache, NULL is just as meaningful as a real
8688 // certificate, so this is the same as supply a
8689 // legitimate-but-unacceptable certificate.
8690 rv = trans->RestartWithCertificate(NULL, &callback);
8691 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8692
8693 // Ensure the certificate was added to the client auth cache before
8694 // allowing the connection to continue restarting.
8695 scoped_refptr<X509Certificate> client_cert;
8696 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8697 &client_cert));
8698 ASSERT_EQ(NULL, client_cert.get());
8699 // Ensure the certificate was NOT cached for the endpoint. This only
8700 // applies to HTTPS requests, but is fine to check for HTTP requests.
8701 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8702 &client_cert));
8703
8704 // Restart the handshake. This will consume ssl_data2, which fails, and
8705 // then consume ssl_data3, which should also fail. The result code is
8706 // checked against what ssl_data3 should return.
8707 rv = callback.WaitForResult();
8708 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8709
8710 // Now that the new handshake has failed, ensure that the client
8711 // certificate was removed from the client auth cache.
8712 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8713 &client_cert));
8714 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8715 &client_cert));
8716 }
8717}
8718
[email protected]e3ceb682011-06-28 23:55:468719TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
8720 HttpStreamFactory::set_use_alternate_protocols(true);
8721 HttpStreamFactory::set_next_protos(kExpectedNPNString);
8722 DisableSpdySessionDomainVerification();
8723
8724 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
8725 SessionDependencies session_deps;
8726 MockCachingHostResolver host_resolver;
8727 net::HttpNetworkSession::Params params;
8728 params.client_socket_factory = &session_deps.socket_factory;
8729 params.host_resolver = &host_resolver;
8730 params.cert_verifier = session_deps.cert_verifier.get();
8731 params.proxy_service = session_deps.proxy_service.get();
8732 params.ssl_config_service = session_deps.ssl_config_service;
8733 params.http_auth_handler_factory =
8734 session_deps.http_auth_handler_factory.get();
8735 params.net_log = session_deps.net_log;
8736 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
8737
8738 SSLSocketDataProvider ssl(true, OK);
8739 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8740 ssl.next_proto = "spdy/2";
8741 ssl.was_npn_negotiated = true;
8742 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8743
8744 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
8745 "https://www.google.com", false, 1, LOWEST));
8746 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
8747 "https://www.gmail.com", false, 3, LOWEST));
8748 MockWrite spdy_writes[] = {
8749 CreateMockWrite(*host1_req, 1),
8750 CreateMockWrite(*host2_req, 4),
8751 };
8752 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8753 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
8754 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
8755 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
8756 MockRead spdy_reads[] = {
8757 CreateMockRead(*host1_resp, 2),
8758 CreateMockRead(*host1_resp_body, 3),
8759 CreateMockRead(*host2_resp, 5),
8760 CreateMockRead(*host2_resp_body, 6),
8761 MockRead(true, 0, 7),
8762 };
8763
8764 scoped_refptr<OrderedSocketData> spdy_data(
8765 new OrderedSocketData(
8766 spdy_reads, arraysize(spdy_reads),
8767 spdy_writes, arraysize(spdy_writes)));
8768 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8769
8770 TestCompletionCallback callback;
8771 HttpRequestInfo request1;
8772 request1.method = "GET";
8773 request1.url = GURL("https://www.google.com/");
8774 request1.load_flags = 0;
8775 HttpNetworkTransaction trans1(session);
8776
8777 int rv = trans1.Start(&request1, &callback, BoundNetLog());
8778 EXPECT_EQ(ERR_IO_PENDING, rv);
8779 EXPECT_EQ(OK, callback.WaitForResult());
8780
8781 const HttpResponseInfo* response = trans1.GetResponseInfo();
8782 ASSERT_TRUE(response != NULL);
8783 ASSERT_TRUE(response->headers != NULL);
8784 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8785
8786 std::string response_data;
8787 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8788 EXPECT_EQ("hello!", response_data);
8789
8790 // Preload www.gmail.com into HostCache.
8791 HostPortPair host_port("www.gmail.com", 443);
8792 HostResolver::RequestInfo resolve_info(host_port);
8793 AddressList ignored;
8794 host_resolver.Resolve(resolve_info, &ignored, NULL, NULL, BoundNetLog());
8795
8796 HttpRequestInfo request2;
8797 request2.method = "GET";
8798 request2.url = GURL("https://www.gmail.com/");
8799 request2.load_flags = 0;
8800 HttpNetworkTransaction trans2(session);
8801
8802 rv = trans2.Start(&request2, &callback, BoundNetLog());
8803 EXPECT_EQ(ERR_IO_PENDING, rv);
8804 EXPECT_EQ(OK, callback.WaitForResult());
8805
8806 response = trans2.GetResponseInfo();
8807 ASSERT_TRUE(response != NULL);
8808 ASSERT_TRUE(response->headers != NULL);
8809 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8810 EXPECT_TRUE(response->was_fetched_via_spdy);
8811 EXPECT_TRUE(response->was_npn_negotiated);
8812 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8813 EXPECT_EQ("hello!", response_data);
8814
8815 HttpStreamFactory::set_next_protos("");
8816 HttpStreamFactory::set_use_alternate_protocols(false);
8817}
8818
8819class OneTimeCachingHostResolver : public net::HostResolver {
8820 public:
8821 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
8822 : host_port_(host_port) {}
8823 virtual ~OneTimeCachingHostResolver() {}
8824
8825 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
8826
8827 // HostResolver methods:
8828 virtual int Resolve(const RequestInfo& info,
8829 AddressList* addresses,
8830 CompletionCallback* callback,
8831 RequestHandle* out_req,
8832 const BoundNetLog& net_log) {
8833 int rv = host_resolver_.Resolve(
8834 info, addresses, callback, out_req, net_log);
8835 if (rv == OK && info.only_use_cached_response() &&
8836 info.host_port_pair().Equals(host_port_)) {
8837 // Discard cache.
8838 host_resolver_.Reset(NULL);
8839 }
8840 return rv;
8841 }
8842
8843 virtual void CancelRequest(RequestHandle req) {
8844 host_resolver_.CancelRequest(req);
8845 }
8846
8847 virtual void AddObserver(Observer* observer) {
8848 return host_resolver_.AddObserver(observer);
8849 }
8850
8851 virtual void RemoveObserver(Observer* observer) {
8852 return host_resolver_.RemoveObserver(observer);
8853 }
8854
8855 private:
8856 MockCachingHostResolver host_resolver_;
8857 const HostPortPair host_port_;
8858};
8859
8860TEST_F(HttpNetworkTransactionTest,
8861 UseIPConnectionPoolingWithHostCacheExpiration) {
8862 HttpStreamFactory::set_use_alternate_protocols(true);
8863 HttpStreamFactory::set_next_protos(kExpectedNPNString);
8864 DisableSpdySessionDomainVerification();
8865
8866 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
8867 SessionDependencies session_deps;
8868 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
8869 net::HttpNetworkSession::Params params;
8870 params.client_socket_factory = &session_deps.socket_factory;
8871 params.host_resolver = &host_resolver;
8872 params.cert_verifier = session_deps.cert_verifier.get();
8873 params.proxy_service = session_deps.proxy_service.get();
8874 params.ssl_config_service = session_deps.ssl_config_service;
8875 params.http_auth_handler_factory =
8876 session_deps.http_auth_handler_factory.get();
8877 params.net_log = session_deps.net_log;
8878 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
8879
8880 SSLSocketDataProvider ssl(true, OK);
8881 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8882 ssl.next_proto = "spdy/2";
8883 ssl.was_npn_negotiated = true;
8884 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8885
8886 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
8887 "https://www.google.com", false, 1, LOWEST));
8888 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
8889 "https://www.gmail.com", false, 3, LOWEST));
8890 MockWrite spdy_writes[] = {
8891 CreateMockWrite(*host1_req, 1),
8892 CreateMockWrite(*host2_req, 4),
8893 };
8894 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8895 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
8896 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
8897 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
8898 MockRead spdy_reads[] = {
8899 CreateMockRead(*host1_resp, 2),
8900 CreateMockRead(*host1_resp_body, 3),
8901 CreateMockRead(*host2_resp, 5),
8902 CreateMockRead(*host2_resp_body, 6),
8903 MockRead(true, 0, 7),
8904 };
8905
8906 scoped_refptr<OrderedSocketData> spdy_data(
8907 new OrderedSocketData(
8908 spdy_reads, arraysize(spdy_reads),
8909 spdy_writes, arraysize(spdy_writes)));
8910 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8911
8912 TestCompletionCallback callback;
8913 HttpRequestInfo request1;
8914 request1.method = "GET";
8915 request1.url = GURL("https://www.google.com/");
8916 request1.load_flags = 0;
8917 HttpNetworkTransaction trans1(session);
8918
8919 int rv = trans1.Start(&request1, &callback, BoundNetLog());
8920 EXPECT_EQ(ERR_IO_PENDING, rv);
8921 EXPECT_EQ(OK, callback.WaitForResult());
8922
8923 const HttpResponseInfo* response = trans1.GetResponseInfo();
8924 ASSERT_TRUE(response != NULL);
8925 ASSERT_TRUE(response->headers != NULL);
8926 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8927
8928 std::string response_data;
8929 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8930 EXPECT_EQ("hello!", response_data);
8931
8932 // Preload cache entries into HostCache.
8933 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
8934 AddressList ignored;
8935 host_resolver.Resolve(resolve_info, &ignored, NULL, NULL, BoundNetLog());
8936
8937 HttpRequestInfo request2;
8938 request2.method = "GET";
8939 request2.url = GURL("https://www.gmail.com/");
8940 request2.load_flags = 0;
8941 HttpNetworkTransaction trans2(session);
8942
8943 rv = trans2.Start(&request2, &callback, BoundNetLog());
8944 EXPECT_EQ(ERR_IO_PENDING, rv);
8945 EXPECT_EQ(OK, callback.WaitForResult());
8946
8947 response = trans2.GetResponseInfo();
8948 ASSERT_TRUE(response != NULL);
8949 ASSERT_TRUE(response->headers != NULL);
8950 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8951 EXPECT_TRUE(response->was_fetched_via_spdy);
8952 EXPECT_TRUE(response->was_npn_negotiated);
8953 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8954 EXPECT_EQ("hello!", response_data);
8955
8956 HttpStreamFactory::set_next_protos("");
8957 HttpStreamFactory::set_use_alternate_protocols(false);
8958}
8959
[email protected]89ceba9a2009-03-21 03:46:068960} // namespace net