blob: e5219a30bc4a6eaab1552cc82ea9032c6df93bf9 [file] [log] [blame]
[email protected]95d88ffe2010-02-04 21:25:331// Copyright (c) 2010 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]6624b4622010-03-29 19:58:3614#include "base/scoped_ptr.h"
[email protected]be1ce6a72010-08-03 14:35:2215#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3516#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1217#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3318#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3219#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1220#include "net/base/net_log.h"
21#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3122#include "net/base/request_priority.h"
[email protected]bd0b6772011-01-11 19:59:3023#include "net/base/ssl_cert_request_info.h"
[email protected]db36938c2009-08-19 21:48:4224#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3325#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5226#include "net/base/test_completion_callback.h"
27#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1228#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0029#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2930#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5731#include "net/http/http_basic_stream.h"
[email protected]3deb9a52010-11-11 00:24:4032#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5233#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5634#include "net/http/http_network_session_peer.h"
[email protected]0877e3d2009-10-17 22:29:5735#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3836#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5237#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5338#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1139#include "net/proxy/proxy_resolver.h"
40#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4441#include "net/socket/client_socket_factory.h"
42#include "net/socket/socket_test_util.h"
43#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5444#include "net/spdy/spdy_framer.h"
45#include "net/spdy/spdy_session.h"
46#include "net/spdy/spdy_session_pool.h"
47#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5248#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1549#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5250
51//-----------------------------------------------------------------------------
52
[email protected]13c8a092010-07-29 06:15:4453namespace {
54
55const string16 kBar(ASCIIToUTF16("bar"));
56const string16 kBar2(ASCIIToUTF16("bar2"));
57const string16 kBar3(ASCIIToUTF16("bar3"));
58const string16 kBaz(ASCIIToUTF16("baz"));
59const string16 kFirst(ASCIIToUTF16("first"));
60const string16 kFoo(ASCIIToUTF16("foo"));
61const string16 kFoo2(ASCIIToUTF16("foo2"));
62const string16 kFoo3(ASCIIToUTF16("foo3"));
63const string16 kFou(ASCIIToUTF16("fou"));
64const string16 kSecond(ASCIIToUTF16("second"));
65const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
66const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
67
68} // namespace
69
[email protected]89ceba9a2009-03-21 03:46:0670namespace net {
71
[email protected]e44de5d2009-06-05 20:12:4572// Helper to manage the lifetimes of the dependencies for a
73// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4474struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5975 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4276 SessionDependencies()
77 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:1578 cert_verifier(new CertVerifier),
[email protected]ebeefff32010-09-15 05:10:0279 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:1080 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0881 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5482 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5483 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5984
85 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4586 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4287 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:1588 cert_verifier(new CertVerifier),
[email protected]db36938c2009-08-19 21:48:4289 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1090 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0891 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5492 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5493 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5994
[email protected]73c45322010-10-01 23:57:5495 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]822581d2010-12-16 17:27:1596 scoped_ptr<CertVerifier> cert_verifier;
[email protected]80d6524d2009-08-18 03:58:0997 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4298 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5999 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50100 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a7ea8832010-07-12 17:54:54101 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59102};
103
[email protected]228ff742009-06-05 01:19:59104HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]73c45322010-10-01 23:57:54105 return new HttpNetworkSession(session_deps->host_resolver.get(),
[email protected]822581d2010-12-16 17:27:15106 session_deps->cert_verifier.get(),
[email protected]2db580532010-10-08 14:32:37107 NULL /* dnsrr_resolver */,
[email protected]345c613b2010-11-22 19:33:18108 NULL /* dns_cert_checker */,
[email protected]7ab5bbd12010-10-19 13:33:21109 NULL /* ssl_host_info_factory */,
[email protected]80d6524d2009-08-18 03:58:09110 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42111 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10112 session_deps->ssl_config_service,
[email protected]87bfa3f2010-09-30 14:54:56113 new SpdySessionPool(NULL),
[email protected]06650c52010-06-03 00:49:17114 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44115 NULL,
[email protected]a7ea8832010-07-12 17:54:54116 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14117}
118
[email protected]89836e22008-09-25 20:33:42119class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52120 public:
[email protected]2ff8b312010-04-26 22:20:54121 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50122 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
123 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54124 spdy::SpdyFramer::set_enable_compression_default(false);
125 }
126
[email protected]0e75a732008-10-16 20:36:09127 virtual void TearDown() {
[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(true);
[email protected]0e75a732008-10-16 20:36:09131 // Empty the current queue.
132 MessageLoop::current()->RunAllPending();
133 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50134 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
135 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09136 }
137
[email protected]3d2a59b2008-09-26 19:44:25138 protected:
139 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52140
[email protected]ff007e162009-05-23 09:13:15141 struct SimpleGetHelperResult {
142 int rv;
143 std::string status_line;
144 std::string response_data;
145 };
initial.commit586acc5fe2008-07-26 22:42:52146
[email protected]31a2bfe2010-02-09 08:03:39147 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
148 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15149 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52150
[email protected]ff007e162009-05-23 09:13:15151 HttpRequestInfo request;
152 request.method = "GET";
153 request.url = GURL("http://www.google.com/");
154 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52155
[email protected]cb9bf6ca2011-01-28 13:15:27156 SessionDependencies session_deps;
157 scoped_ptr<HttpTransaction> trans(
158 new HttpNetworkTransaction(CreateSession(&session_deps)));
159
[email protected]31a2bfe2010-02-09 08:03:39160 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59161 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52162
[email protected]ff007e162009-05-23 09:13:15163 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52164
[email protected]169d0012010-05-10 23:20:12165 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]3deb9a52010-11-11 00:24:40166 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
[email protected]169d0012010-05-10 23:20:12167 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15168 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52169
[email protected]ff007e162009-05-23 09:13:15170 out.rv = callback.WaitForResult();
171 if (out.rv != OK)
172 return out;
173
174 const HttpResponseInfo* response = trans->GetResponseInfo();
175 EXPECT_TRUE(response != NULL);
176
177 EXPECT_TRUE(response->headers != NULL);
178 out.status_line = response->headers->GetStatusLine();
179
180 rv = ReadTransaction(trans.get(), &out.response_data);
181 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40182
183 net::CapturingNetLog::EntryList entries;
184 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39185 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40186 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12187 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39188 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40189 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39190 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
191 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15192
[email protected]b2fcd0e2010-12-01 15:19:40193 CapturingNetLog::Entry entry = entries[pos];
[email protected]3deb9a52010-11-11 00:24:40194 NetLogHttpRequestParameter* request_params =
195 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
196 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
197 EXPECT_EQ("Host: www.google.com\r\n"
198 "Connection: keep-alive\r\n\r\n",
199 request_params->GetHeaders().ToString());
200
[email protected]aecfbf22008-10-16 02:02:47201 return out;
[email protected]ff007e162009-05-23 09:13:15202 }
initial.commit586acc5fe2008-07-26 22:42:52203
[email protected]ff007e162009-05-23 09:13:15204 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
205 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52206
[email protected]ff007e162009-05-23 09:13:15207 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15208};
[email protected]231d5a32008-09-13 00:45:27209
[email protected]15a5ccf82008-10-23 19:57:43210// Fill |str| with a long header list that consumes >= |size| bytes.
211void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19212 const char* row =
213 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
214 const int sizeof_row = strlen(row);
215 const int num_rows = static_cast<int>(
216 ceil(static_cast<float>(size) / sizeof_row));
217 const int sizeof_data = num_rows * sizeof_row;
218 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43219 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51220
[email protected]4ddaf2502008-10-23 18:26:19221 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43222 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19223}
224
[email protected]385a4672009-03-11 22:21:29225// Alternative functions that eliminate randomness and dependency on the local
226// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20227void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29228 static const uint8 bytes[] = {
229 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
230 };
231 static size_t current_byte = 0;
232 for (size_t i = 0; i < n; ++i) {
233 output[i] = bytes[current_byte++];
234 current_byte %= arraysize(bytes);
235 }
236}
237
[email protected]fe2bc6a2009-03-23 16:52:20238void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29239 static const uint8 bytes[] = {
240 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
241 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
242 };
243 static size_t current_byte = 0;
244 for (size_t i = 0; i < n; ++i) {
245 output[i] = bytes[current_byte++];
246 current_byte %= arraysize(bytes);
247 }
248}
249
[email protected]fe2bc6a2009-03-23 16:52:20250std::string MockGetHostName() {
251 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29252}
253
[email protected]e60e47a2010-07-14 03:37:18254template<typename ParentPool>
255class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31256 public:
[email protected]e60e47a2010-07-14 03:37:18257 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
258
[email protected]d80a4322009-08-14 07:07:49259 const std::string last_group_name_received() const {
260 return last_group_name_;
261 }
262
[email protected]684970b2009-08-14 04:54:46263 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49264 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31265 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31266 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46267 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53268 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31269 last_group_name_ = group_name;
270 return ERR_IO_PENDING;
271 }
[email protected]04e5be32009-06-26 20:00:31272 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21273 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31274 virtual void ReleaseSocket(const std::string& group_name,
275 ClientSocket* socket) {}
276 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31277 virtual int IdleSocketCount() const {
278 return 0;
279 }
280 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
281 return 0;
282 }
283 virtual LoadState GetLoadState(const std::string& group_name,
284 const ClientSocketHandle* handle) const {
285 return LOAD_STATE_IDLE;
286 }
[email protected]a796bcec2010-03-22 17:17:26287 virtual base::TimeDelta ConnectionTimeout() const {
288 return base::TimeDelta();
289 }
[email protected]d80a4322009-08-14 07:07:49290
291 private:
[email protected]04e5be32009-06-26 20:00:31292 std::string last_group_name_;
293};
294
[email protected]2d731a32010-04-29 01:04:06295typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11296CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13297typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
298CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06299typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11300CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18301typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
302CaptureGroupNameSSLSocketPool;
303
304template<typename ParentPool>
305CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
306 HttpNetworkSession* session)
307 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
308
309template<>
[email protected]2df19bb2010-08-25 20:13:46310CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
311 HttpNetworkSession* session)
312 : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
313 NULL, NULL) {}
314
315template<>
[email protected]e60e47a2010-07-14 03:37:18316CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
317 HttpNetworkSession* session)
[email protected]822581d2010-12-16 17:27:15318 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(),
319 session->cert_verifier(), NULL, NULL,
[email protected]345c613b2010-11-22 19:33:18320 NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11321
[email protected]231d5a32008-09-13 00:45:27322//-----------------------------------------------------------------------------
323
[email protected]dae22c52010-07-30 02:16:35324// This is the expected list of advertised protocols from the browser's NPN
325// list.
326static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
327
328// This is the expected return from a current server advertising SPDY.
329static const char kAlternateProtocolHttpHeader[] =
330 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
331
[email protected]231d5a32008-09-13 00:45:27332TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59333 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40334 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43335 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27336}
337
338TEST_F(HttpNetworkTransactionTest, SimpleGET) {
339 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35340 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
341 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42342 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27343 };
[email protected]31a2bfe2010-02-09 08:03:39344 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
345 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42346 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27347 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
348 EXPECT_EQ("hello world", out.response_data);
349}
350
351// Response with no status line.
352TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
353 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35354 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42355 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27356 };
[email protected]31a2bfe2010-02-09 08:03:39357 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
358 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42359 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27360 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
361 EXPECT_EQ("hello world", out.response_data);
362}
363
364// Allow up to 4 bytes of junk to precede status line.
365TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
366 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35367 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42368 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27369 };
[email protected]31a2bfe2010-02-09 08:03:39370 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
371 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42372 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27373 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
374 EXPECT_EQ("DATA", out.response_data);
375}
376
377// Allow up to 4 bytes of junk to precede status line.
378TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
379 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35380 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42381 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27382 };
[email protected]31a2bfe2010-02-09 08:03:39383 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
384 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42385 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27386 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
387 EXPECT_EQ("DATA", out.response_data);
388}
389
390// Beyond 4 bytes of slop and it should fail to find a status line.
391TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
392 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35393 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42394 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27395 };
[email protected]31a2bfe2010-02-09 08:03:39396 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
397 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42398 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25399 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
400 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27401}
402
403// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
404TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
405 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35406 MockRead("\n"),
407 MockRead("\n"),
408 MockRead("Q"),
409 MockRead("J"),
410 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42411 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27412 };
[email protected]31a2bfe2010-02-09 08:03:39413 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
414 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42415 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27416 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
417 EXPECT_EQ("DATA", out.response_data);
418}
419
420// Close the connection before enough bytes to have a status line.
421TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
422 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35423 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42424 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27425 };
[email protected]31a2bfe2010-02-09 08:03:39426 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
427 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42428 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27429 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
430 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52431}
432
[email protected]f9d44aa2008-09-23 23:57:17433// Simulate a 204 response, lacking a Content-Length header, sent over a
434// persistent connection. The response should still terminate since a 204
435// cannot have a response body.
436TEST_F(HttpNetworkTransactionTest, StopsReading204) {
437 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35438 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
439 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42440 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17441 };
[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]f9d44aa2008-09-23 23:57:17445 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
446 EXPECT_EQ("", out.response_data);
447}
448
[email protected]0877e3d2009-10-17 22:29:57449// A simple request using chunked encoding with some extra data after.
450// (Like might be seen in a pipelined response.)
451TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
452 MockRead data_reads[] = {
453 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
454 MockRead("5\r\nHello\r\n"),
455 MockRead("1\r\n"),
456 MockRead(" \r\n"),
457 MockRead("5\r\nworld\r\n"),
458 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
459 MockRead(false, OK),
460 };
[email protected]31a2bfe2010-02-09 08:03:39461 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
462 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57463 EXPECT_EQ(OK, out.rv);
464 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
465 EXPECT_EQ("Hello world", out.response_data);
466}
467
[email protected]9fe44f52010-09-23 18:36:00468// Next tests deal with http://crbug.com/56344.
469
470TEST_F(HttpNetworkTransactionTest,
471 MultipleContentLengthHeadersNoTransferEncoding) {
472 MockRead data_reads[] = {
473 MockRead("HTTP/1.1 200 OK\r\n"),
474 MockRead("Content-Length: 10\r\n"),
475 MockRead("Content-Length: 5\r\n\r\n"),
476 };
477 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
478 arraysize(data_reads));
479 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
480}
481
482TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04483 DuplicateContentLengthHeadersNoTransferEncoding) {
484 MockRead data_reads[] = {
485 MockRead("HTTP/1.1 200 OK\r\n"),
486 MockRead("Content-Length: 5\r\n"),
487 MockRead("Content-Length: 5\r\n\r\n"),
488 MockRead("Hello"),
489 };
490 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
491 arraysize(data_reads));
492 EXPECT_EQ(OK, out.rv);
493 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
494 EXPECT_EQ("Hello", out.response_data);
495}
496
497TEST_F(HttpNetworkTransactionTest,
498 ComplexContentLengthHeadersNoTransferEncoding) {
499 // More than 2 dupes.
500 {
501 MockRead data_reads[] = {
502 MockRead("HTTP/1.1 200 OK\r\n"),
503 MockRead("Content-Length: 5\r\n"),
504 MockRead("Content-Length: 5\r\n"),
505 MockRead("Content-Length: 5\r\n\r\n"),
506 MockRead("Hello"),
507 };
508 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
509 arraysize(data_reads));
510 EXPECT_EQ(OK, out.rv);
511 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
512 EXPECT_EQ("Hello", out.response_data);
513 }
514 // HTTP/1.0
515 {
516 MockRead data_reads[] = {
517 MockRead("HTTP/1.0 200 OK\r\n"),
518 MockRead("Content-Length: 5\r\n"),
519 MockRead("Content-Length: 5\r\n"),
520 MockRead("Content-Length: 5\r\n\r\n"),
521 MockRead("Hello"),
522 };
523 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
524 arraysize(data_reads));
525 EXPECT_EQ(OK, out.rv);
526 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
527 EXPECT_EQ("Hello", out.response_data);
528 }
529 // 2 dupes and one mismatched.
530 {
531 MockRead data_reads[] = {
532 MockRead("HTTP/1.1 200 OK\r\n"),
533 MockRead("Content-Length: 10\r\n"),
534 MockRead("Content-Length: 10\r\n"),
535 MockRead("Content-Length: 5\r\n\r\n"),
536 };
537 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
538 arraysize(data_reads));
539 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
540 }
541}
542
543TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00544 MultipleContentLengthHeadersTransferEncoding) {
545 MockRead data_reads[] = {
546 MockRead("HTTP/1.1 200 OK\r\n"),
547 MockRead("Content-Length: 666\r\n"),
548 MockRead("Content-Length: 1337\r\n"),
549 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
550 MockRead("5\r\nHello\r\n"),
551 MockRead("1\r\n"),
552 MockRead(" \r\n"),
553 MockRead("5\r\nworld\r\n"),
554 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
555 MockRead(false, OK),
556 };
557 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
558 arraysize(data_reads));
559 EXPECT_EQ(OK, out.rv);
560 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
561 EXPECT_EQ("Hello world", out.response_data);
562}
563
[email protected]ef0faf2e72009-03-05 23:27:23564// Do a request using the HEAD method. Verify that we don't try to read the
565// message body (since HEAD has none).
566TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:42567 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23568 request.method = "HEAD";
569 request.url = GURL("http://www.google.com/");
570 request.load_flags = 0;
571
[email protected]cb9bf6ca2011-01-28 13:15:27572 SessionDependencies session_deps;
573 scoped_ptr<HttpTransaction> trans(
574 new HttpNetworkTransaction(CreateSession(&session_deps)));
575
[email protected]ef0faf2e72009-03-05 23:27:23576 MockWrite data_writes1[] = {
577 MockWrite("HEAD / HTTP/1.1\r\n"
578 "Host: www.google.com\r\n"
579 "Connection: keep-alive\r\n"
580 "Content-Length: 0\r\n\r\n"),
581 };
582 MockRead data_reads1[] = {
583 MockRead("HTTP/1.1 404 Not Found\r\n"),
584 MockRead("Server: Blah\r\n"),
585 MockRead("Content-Length: 1234\r\n\r\n"),
586
587 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42588 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23589 };
590
[email protected]31a2bfe2010-02-09 08:03:39591 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
592 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59593 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23594
595 TestCompletionCallback callback1;
596
[email protected]5a1d7ca2010-04-28 20:12:27597 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42598 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23599
600 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42601 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23602
[email protected]1c773ea12009-04-28 19:58:42603 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23604 EXPECT_FALSE(response == NULL);
605
606 // Check that the headers got parsed.
607 EXPECT_TRUE(response->headers != NULL);
608 EXPECT_EQ(1234, response->headers->GetContentLength());
609 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
610
611 std::string server_header;
612 void* iter = NULL;
613 bool has_server_header = response->headers->EnumerateHeader(
614 &iter, "Server", &server_header);
615 EXPECT_TRUE(has_server_header);
616 EXPECT_EQ("Blah", server_header);
617
618 // Reading should give EOF right away, since there is no message body
619 // (despite non-zero content-length).
620 std::string response_data;
621 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42622 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23623 EXPECT_EQ("", response_data);
624}
625
initial.commit586acc5fe2008-07-26 22:42:52626TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59627 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27628 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52629
630 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35631 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
632 MockRead("hello"),
633 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
634 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42635 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52636 };
[email protected]31a2bfe2010-02-09 08:03:39637 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59638 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52639
[email protected]0b0bf032010-09-21 18:08:50640 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52641 "hello", "world"
642 };
643
644 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42645 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52646 request.method = "GET";
647 request.url = GURL("http://www.google.com/");
648 request.load_flags = 0;
649
[email protected]cb9bf6ca2011-01-28 13:15:27650 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
651
initial.commit586acc5fe2008-07-26 22:42:52652 TestCompletionCallback callback;
653
[email protected]5a1d7ca2010-04-28 20:12:27654 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42655 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52656
657 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42658 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52659
[email protected]1c773ea12009-04-28 19:58:42660 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52661 EXPECT_TRUE(response != NULL);
662
663 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25664 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52665
666 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57667 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42668 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25669 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52670 }
671}
672
673TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]1c773ea12009-04-28 19:58:42674 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52675 request.method = "POST";
676 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42677 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52678 request.upload_data->AppendBytes("foo", 3);
679 request.load_flags = 0;
680
[email protected]cb9bf6ca2011-01-28 13:15:27681 SessionDependencies session_deps;
682 scoped_ptr<HttpTransaction> trans(
683 new HttpNetworkTransaction(CreateSession(&session_deps)));
684
initial.commit586acc5fe2008-07-26 22:42:52685 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35686 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
687 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
688 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42689 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52690 };
[email protected]31a2bfe2010-02-09 08:03:39691 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59692 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52693
694 TestCompletionCallback callback;
695
[email protected]5a1d7ca2010-04-28 20:12:27696 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42697 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52698
699 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42700 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52701
[email protected]1c773ea12009-04-28 19:58:42702 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52703 EXPECT_TRUE(response != NULL);
704
705 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25706 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52707
708 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57709 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42710 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25711 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52712}
713
[email protected]3a2d3662009-03-27 03:49:14714// This test is almost the same as Ignores100 above, but the response contains
715// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57716// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14717TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:42718 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14719 request.method = "GET";
720 request.url = GURL("http://www.foo.com/");
721 request.load_flags = 0;
722
[email protected]cb9bf6ca2011-01-28 13:15:27723 SessionDependencies session_deps;
724 scoped_ptr<HttpTransaction> trans(
725 new HttpNetworkTransaction(CreateSession(&session_deps)));
726
[email protected]3a2d3662009-03-27 03:49:14727 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57728 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
729 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14730 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42731 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14732 };
[email protected]31a2bfe2010-02-09 08:03:39733 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59734 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14735
736 TestCompletionCallback callback;
737
[email protected]5a1d7ca2010-04-28 20:12:27738 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42739 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14740
741 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42742 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14743
[email protected]1c773ea12009-04-28 19:58:42744 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14745 EXPECT_TRUE(response != NULL);
746
747 EXPECT_TRUE(response->headers != NULL);
748 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
749
750 std::string response_data;
751 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42752 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14753 EXPECT_EQ("hello world", response_data);
754}
755
[email protected]ee9410e72010-01-07 01:42:38756TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
[email protected]ee9410e72010-01-07 01:42:38757 HttpRequestInfo request;
758 request.method = "POST";
759 request.url = GURL("http://www.foo.com/");
760 request.load_flags = 0;
761
[email protected]cb9bf6ca2011-01-28 13:15:27762 SessionDependencies session_deps;
763 scoped_ptr<HttpTransaction> trans(
764 new HttpNetworkTransaction(CreateSession(&session_deps)));
765
[email protected]ee9410e72010-01-07 01:42:38766 MockRead data_reads[] = {
767 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
768 MockRead(true, 0),
769 };
[email protected]31a2bfe2010-02-09 08:03:39770 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38771 session_deps.socket_factory.AddSocketDataProvider(&data);
772
773 TestCompletionCallback callback;
774
[email protected]5a1d7ca2010-04-28 20:12:27775 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38776 EXPECT_EQ(ERR_IO_PENDING, rv);
777
778 rv = callback.WaitForResult();
779 EXPECT_EQ(OK, rv);
780
781 std::string response_data;
782 rv = ReadTransaction(trans.get(), &response_data);
783 EXPECT_EQ(OK, rv);
784 EXPECT_EQ("", response_data);
785}
786
787TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:38788 HttpRequestInfo request;
789 request.method = "POST";
790 request.url = GURL("http://www.foo.com/");
791 request.load_flags = 0;
792
[email protected]cb9bf6ca2011-01-28 13:15:27793 SessionDependencies session_deps;
794 scoped_ptr<HttpTransaction> trans(
795 new HttpNetworkTransaction(CreateSession(&session_deps)));
796
[email protected]ee9410e72010-01-07 01:42:38797 MockRead data_reads[] = {
798 MockRead(true, 0),
799 };
[email protected]31a2bfe2010-02-09 08:03:39800 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38801 session_deps.socket_factory.AddSocketDataProvider(&data);
802
803 TestCompletionCallback callback;
804
[email protected]5a1d7ca2010-04-28 20:12:27805 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38806 EXPECT_EQ(ERR_IO_PENDING, rv);
807
808 rv = callback.WaitForResult();
809 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
810}
811
[email protected]3d2a59b2008-09-26 19:44:25812// read_failure specifies a read failure that should cause the network
813// transaction to resend the request.
814void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
815 const MockRead& read_failure) {
[email protected]1c773ea12009-04-28 19:58:42816 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52817 request.method = "GET";
818 request.url = GURL("http://www.foo.com/");
819 request.load_flags = 0;
820
[email protected]cb9bf6ca2011-01-28 13:15:27821 SessionDependencies session_deps;
822 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
823
initial.commit586acc5fe2008-07-26 22:42:52824 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35825 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
826 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25827 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52828 };
[email protected]31a2bfe2010-02-09 08:03:39829 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59830 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52831
832 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35833 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
834 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42835 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52836 };
[email protected]31a2bfe2010-02-09 08:03:39837 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59838 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52839
840 const char* kExpectedResponseData[] = {
841 "hello", "world"
842 };
843
844 for (int i = 0; i < 2; ++i) {
845 TestCompletionCallback callback;
846
[email protected]5695b8c2009-09-30 21:36:43847 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52848
[email protected]5a1d7ca2010-04-28 20:12:27849 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42850 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52851
852 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42853 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52854
[email protected]1c773ea12009-04-28 19:58:42855 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52856 EXPECT_TRUE(response != NULL);
857
858 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25859 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52860
861 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57862 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42863 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25864 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52865 }
866}
[email protected]3d2a59b2008-09-26 19:44:25867
868TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42869 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25870 KeepAliveConnectionResendRequestTest(read_failure);
871}
872
873TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42874 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25875 KeepAliveConnectionResendRequestTest(read_failure);
876}
877
878TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42879 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25880 request.method = "GET";
881 request.url = GURL("http://www.google.com/");
882 request.load_flags = 0;
883
[email protected]cb9bf6ca2011-01-28 13:15:27884 SessionDependencies session_deps;
885 scoped_ptr<HttpTransaction> trans(
886 new HttpNetworkTransaction(CreateSession(&session_deps)));
887
[email protected]3d2a59b2008-09-26 19:44:25888 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42889 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35890 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
891 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42892 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25893 };
[email protected]31a2bfe2010-02-09 08:03:39894 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59895 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25896
897 TestCompletionCallback callback;
898
[email protected]5a1d7ca2010-04-28 20:12:27899 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42900 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25901
902 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42903 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25904
[email protected]1c773ea12009-04-28 19:58:42905 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25906 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25907}
908
909// What do various browsers do when the server closes a non-keepalive
910// connection without sending any response header or body?
911//
912// IE7: error page
913// Safari 3.1.2 (Windows): error page
914// Firefox 3.0.1: blank page
915// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42916// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
917// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25918TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
919 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42920 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35921 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
922 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42923 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25924 };
[email protected]31a2bfe2010-02-09 08:03:39925 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
926 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42927 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25928}
[email protected]038e9a32008-10-08 22:40:16929
[email protected]0b0bf032010-09-21 18:08:50930// Test that we correctly reuse a keep-alive connection after not explicitly
931// reading the body.
932TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13933 HttpRequestInfo request;
934 request.method = "GET";
935 request.url = GURL("http://www.foo.com/");
936 request.load_flags = 0;
937
[email protected]cb9bf6ca2011-01-28 13:15:27938 SessionDependencies session_deps;
939 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
940
[email protected]0b0bf032010-09-21 18:08:50941 // Note that because all these reads happen in the same
942 // StaticSocketDataProvider, it shows that the same socket is being reused for
943 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13944 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50945 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
946 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13947 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50948 MockRead("HTTP/1.1 302 Found\r\n"
949 "Content-Length: 0\r\n\r\n"),
950 MockRead("HTTP/1.1 302 Found\r\n"
951 "Content-Length: 5\r\n\r\n"
952 "hello"),
953 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
954 "Content-Length: 0\r\n\r\n"),
955 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
956 "Content-Length: 5\r\n\r\n"
957 "hello"),
[email protected]fc31d6a42010-06-24 18:05:13958 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
959 MockRead("hello"),
960 };
961 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
962 session_deps.socket_factory.AddSocketDataProvider(&data1);
963
964 MockRead data2_reads[] = {
965 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
966 };
967 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
968 session_deps.socket_factory.AddSocketDataProvider(&data2);
969
[email protected]0b0bf032010-09-21 18:08:50970 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
971 std::string response_lines[kNumUnreadBodies];
972
973 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:13974 TestCompletionCallback callback;
975
976 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
977
978 int rv = trans->Start(&request, &callback, BoundNetLog());
979 EXPECT_EQ(ERR_IO_PENDING, rv);
980
981 rv = callback.WaitForResult();
982 EXPECT_EQ(OK, rv);
983
984 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:50985 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:13986
[email protected]0b0bf032010-09-21 18:08:50987 ASSERT_TRUE(response->headers != NULL);
988 response_lines[i] = response->headers->GetStatusLine();
989
990 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:13991 }
[email protected]0b0bf032010-09-21 18:08:50992
993 const char* const kStatusLines[] = {
994 "HTTP/1.1 204 No Content",
995 "HTTP/1.1 205 Reset Content",
996 "HTTP/1.1 304 Not Modified",
997 "HTTP/1.1 302 Found",
998 "HTTP/1.1 302 Found",
999 "HTTP/1.1 301 Moved Permanently",
1000 "HTTP/1.1 301 Moved Permanently",
1001 };
1002
1003 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1004 forgot_to_update_kStatusLines);
1005
1006 for (int i = 0; i < kNumUnreadBodies; ++i)
1007 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1008
1009 TestCompletionCallback callback;
1010 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1011 int rv = trans->Start(&request, &callback, BoundNetLog());
1012 EXPECT_EQ(ERR_IO_PENDING, rv);
1013 rv = callback.WaitForResult();
1014 EXPECT_EQ(OK, rv);
1015 const HttpResponseInfo* response = trans->GetResponseInfo();
1016 ASSERT_TRUE(response != NULL);
1017 ASSERT_TRUE(response->headers != NULL);
1018 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1019 std::string response_data;
1020 rv = ReadTransaction(trans.get(), &response_data);
1021 EXPECT_EQ(OK, rv);
1022 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131023}
1024
[email protected]038e9a32008-10-08 22:40:161025// Test the request-challenge-retry sequence for basic auth.
1026// (basic auth is the easiest to mock, because it has no randomness).
1027TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421028 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161029 request.method = "GET";
1030 request.url = GURL("http://www.google.com/");
1031 request.load_flags = 0;
1032
[email protected]cb9bf6ca2011-01-28 13:15:271033 SessionDependencies session_deps;
1034 scoped_ptr<HttpTransaction> trans(
1035 new HttpNetworkTransaction(CreateSession(&session_deps)));
1036
[email protected]f9ee6b52008-11-08 06:46:231037 MockWrite data_writes1[] = {
1038 MockWrite("GET / HTTP/1.1\r\n"
1039 "Host: www.google.com\r\n"
1040 "Connection: keep-alive\r\n\r\n"),
1041 };
1042
[email protected]038e9a32008-10-08 22:40:161043 MockRead data_reads1[] = {
1044 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1045 // Give a couple authenticate options (only the middle one is actually
1046 // supported).
[email protected]22927ad2009-09-21 19:56:191047 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161048 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1049 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1050 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1051 // Large content-length -- won't matter, as connection will be reset.
1052 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421053 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161054 };
1055
1056 // After calling trans->RestartWithAuth(), this is the request we should
1057 // be issuing -- the final header line contains the credentials.
1058 MockWrite data_writes2[] = {
1059 MockWrite("GET / HTTP/1.1\r\n"
1060 "Host: www.google.com\r\n"
1061 "Connection: keep-alive\r\n"
1062 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1063 };
1064
1065 // Lastly, the server responds with the actual content.
1066 MockRead data_reads2[] = {
1067 MockRead("HTTP/1.0 200 OK\r\n"),
1068 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1069 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421070 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161071 };
1072
[email protected]31a2bfe2010-02-09 08:03:391073 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1074 data_writes1, arraysize(data_writes1));
1075 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1076 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591077 session_deps.socket_factory.AddSocketDataProvider(&data1);
1078 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161079
1080 TestCompletionCallback callback1;
1081
[email protected]5a1d7ca2010-04-28 20:12:271082 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421083 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161084
1085 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421086 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161087
[email protected]1c773ea12009-04-28 19:58:421088 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161089 EXPECT_FALSE(response == NULL);
1090
1091 // The password prompt info should have been set in response->auth_challenge.
1092 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1093
[email protected]71e4573a2009-05-21 22:03:001094 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161095 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1096 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1097
1098 TestCompletionCallback callback2;
1099
[email protected]13c8a092010-07-29 06:15:441100 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421101 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161102
1103 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421104 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161105
1106 response = trans->GetResponseInfo();
1107 EXPECT_FALSE(response == NULL);
1108 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1109 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161110}
1111
[email protected]861fcd52009-08-26 02:33:461112TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:461113 HttpRequestInfo request;
1114 request.method = "GET";
1115 request.url = GURL("http://www.google.com/");
1116 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1117
[email protected]cb9bf6ca2011-01-28 13:15:271118 SessionDependencies session_deps;
1119 scoped_ptr<HttpTransaction> trans(
1120 new HttpNetworkTransaction(CreateSession(&session_deps)));
1121
[email protected]861fcd52009-08-26 02:33:461122 MockWrite data_writes[] = {
1123 MockWrite("GET / HTTP/1.1\r\n"
1124 "Host: www.google.com\r\n"
1125 "Connection: keep-alive\r\n\r\n"),
1126 };
1127
1128 MockRead data_reads[] = {
1129 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1130 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1131 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1132 // Large content-length -- won't matter, as connection will be reset.
1133 MockRead("Content-Length: 10000\r\n\r\n"),
1134 MockRead(false, ERR_FAILED),
1135 };
1136
[email protected]31a2bfe2010-02-09 08:03:391137 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1138 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591139 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461140 TestCompletionCallback callback;
1141
[email protected]5a1d7ca2010-04-28 20:12:271142 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461143 EXPECT_EQ(ERR_IO_PENDING, rv);
1144
1145 rv = callback.WaitForResult();
1146 EXPECT_EQ(0, rv);
1147
1148 const HttpResponseInfo* response = trans->GetResponseInfo();
1149 ASSERT_FALSE(response == NULL);
1150 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1151}
1152
[email protected]2d2697f92009-02-18 21:00:321153// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1154// connection.
1155TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]1c773ea12009-04-28 19:58:421156 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321157 request.method = "GET";
1158 request.url = GURL("http://www.google.com/");
1159 request.load_flags = 0;
1160
[email protected]cb9bf6ca2011-01-28 13:15:271161 SessionDependencies session_deps;
1162 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1163
[email protected]2d2697f92009-02-18 21:00:321164 MockWrite data_writes1[] = {
1165 MockWrite("GET / HTTP/1.1\r\n"
1166 "Host: www.google.com\r\n"
1167 "Connection: keep-alive\r\n\r\n"),
1168
1169 // After calling trans->RestartWithAuth(), this is the request we should
1170 // be issuing -- the final header line contains the credentials.
1171 MockWrite("GET / HTTP/1.1\r\n"
1172 "Host: www.google.com\r\n"
1173 "Connection: keep-alive\r\n"
1174 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1175 };
1176
1177 MockRead data_reads1[] = {
1178 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1179 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1180 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1181 MockRead("Content-Length: 14\r\n\r\n"),
1182 MockRead("Unauthorized\r\n"),
1183
1184 // Lastly, the server responds with the actual content.
1185 MockRead("HTTP/1.1 200 OK\r\n"),
1186 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501187 MockRead("Content-Length: 5\r\n\r\n"),
1188 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321189 };
1190
[email protected]31a2bfe2010-02-09 08:03:391191 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1192 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591193 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321194
1195 TestCompletionCallback callback1;
1196
[email protected]0b0bf032010-09-21 18:08:501197 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271198 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421199 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321200
1201 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421202 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321203
[email protected]1c773ea12009-04-28 19:58:421204 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321205 EXPECT_FALSE(response == NULL);
1206
1207 // The password prompt info should have been set in response->auth_challenge.
1208 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1209
[email protected]71e4573a2009-05-21 22:03:001210 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321211 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1212 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1213
1214 TestCompletionCallback callback2;
1215
[email protected]13c8a092010-07-29 06:15:441216 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421217 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321218
1219 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421220 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321221
1222 response = trans->GetResponseInfo();
1223 EXPECT_FALSE(response == NULL);
1224 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501225 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321226}
1227
1228// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1229// connection and with no response body to drain.
1230TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:421231 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321232 request.method = "GET";
1233 request.url = GURL("http://www.google.com/");
1234 request.load_flags = 0;
1235
[email protected]cb9bf6ca2011-01-28 13:15:271236 SessionDependencies session_deps;
1237 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1238
[email protected]2d2697f92009-02-18 21:00:321239 MockWrite data_writes1[] = {
1240 MockWrite("GET / HTTP/1.1\r\n"
1241 "Host: www.google.com\r\n"
1242 "Connection: keep-alive\r\n\r\n"),
1243
1244 // After calling trans->RestartWithAuth(), this is the request we should
1245 // be issuing -- the final header line contains the credentials.
1246 MockWrite("GET / HTTP/1.1\r\n"
1247 "Host: www.google.com\r\n"
1248 "Connection: keep-alive\r\n"
1249 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1250 };
1251
[email protected]2d2697f92009-02-18 21:00:321252 MockRead data_reads1[] = {
1253 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1254 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311255 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321256
1257 // Lastly, the server responds with the actual content.
1258 MockRead("HTTP/1.1 200 OK\r\n"),
1259 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501260 MockRead("Content-Length: 5\r\n\r\n"),
1261 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321262 };
1263
[email protected]31a2bfe2010-02-09 08:03:391264 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1265 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591266 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321267
1268 TestCompletionCallback callback1;
1269
[email protected]0b0bf032010-09-21 18:08:501270 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271271 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421272 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321273
1274 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421275 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321276
[email protected]1c773ea12009-04-28 19:58:421277 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321278 EXPECT_FALSE(response == NULL);
1279
1280 // The password prompt info should have been set in response->auth_challenge.
1281 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1282
[email protected]71e4573a2009-05-21 22:03:001283 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321284 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1285 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1286
1287 TestCompletionCallback callback2;
1288
[email protected]13c8a092010-07-29 06:15:441289 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421290 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321291
1292 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421293 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321294
1295 response = trans->GetResponseInfo();
1296 EXPECT_FALSE(response == NULL);
1297 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501298 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321299}
1300
1301// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1302// connection and with a large response body to drain.
1303TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:421304 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321305 request.method = "GET";
1306 request.url = GURL("http://www.google.com/");
1307 request.load_flags = 0;
1308
[email protected]cb9bf6ca2011-01-28 13:15:271309 SessionDependencies session_deps;
1310 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1311
[email protected]2d2697f92009-02-18 21:00:321312 MockWrite data_writes1[] = {
1313 MockWrite("GET / HTTP/1.1\r\n"
1314 "Host: www.google.com\r\n"
1315 "Connection: keep-alive\r\n\r\n"),
1316
1317 // After calling trans->RestartWithAuth(), this is the request we should
1318 // be issuing -- the final header line contains the credentials.
1319 MockWrite("GET / HTTP/1.1\r\n"
1320 "Host: www.google.com\r\n"
1321 "Connection: keep-alive\r\n"
1322 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1323 };
1324
1325 // Respond with 5 kb of response body.
1326 std::string large_body_string("Unauthorized");
1327 large_body_string.append(5 * 1024, ' ');
1328 large_body_string.append("\r\n");
1329
1330 MockRead data_reads1[] = {
1331 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1332 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1333 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1334 // 5134 = 12 + 5 * 1024 + 2
1335 MockRead("Content-Length: 5134\r\n\r\n"),
1336 MockRead(true, large_body_string.data(), large_body_string.size()),
1337
1338 // Lastly, the server responds with the actual content.
1339 MockRead("HTTP/1.1 200 OK\r\n"),
1340 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501341 MockRead("Content-Length: 5\r\n\r\n"),
1342 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321343 };
1344
[email protected]31a2bfe2010-02-09 08:03:391345 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1346 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591347 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321348
1349 TestCompletionCallback callback1;
1350
[email protected]0b0bf032010-09-21 18:08:501351 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271352 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421353 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321354
1355 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421356 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321357
[email protected]1c773ea12009-04-28 19:58:421358 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321359 EXPECT_FALSE(response == NULL);
1360
1361 // The password prompt info should have been set in response->auth_challenge.
1362 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1363
[email protected]71e4573a2009-05-21 22:03:001364 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321365 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1366 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1367
1368 TestCompletionCallback callback2;
1369
[email protected]13c8a092010-07-29 06:15:441370 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421371 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321372
1373 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421374 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321375
1376 response = trans->GetResponseInfo();
1377 EXPECT_FALSE(response == NULL);
1378 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501379 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321380}
1381
1382// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311383// connection, but the server gets impatient and closes the connection.
1384TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:311385 HttpRequestInfo request;
1386 request.method = "GET";
1387 request.url = GURL("http://www.google.com/");
1388 request.load_flags = 0;
1389
[email protected]cb9bf6ca2011-01-28 13:15:271390 SessionDependencies session_deps;
1391 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1392
[email protected]11203f012009-11-12 23:02:311393 MockWrite data_writes1[] = {
1394 MockWrite("GET / HTTP/1.1\r\n"
1395 "Host: www.google.com\r\n"
1396 "Connection: keep-alive\r\n\r\n"),
1397 // This simulates the seemingly successful write to a closed connection
1398 // if the bug is not fixed.
1399 MockWrite("GET / HTTP/1.1\r\n"
1400 "Host: www.google.com\r\n"
1401 "Connection: keep-alive\r\n"
1402 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1403 };
1404
1405 MockRead data_reads1[] = {
1406 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1407 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1408 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1409 MockRead("Content-Length: 14\r\n\r\n"),
1410 // Tell MockTCPClientSocket to simulate the server closing the connection.
1411 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1412 MockRead("Unauthorized\r\n"),
1413 MockRead(false, OK), // The server closes the connection.
1414 };
1415
1416 // After calling trans->RestartWithAuth(), this is the request we should
1417 // be issuing -- the final header line contains the credentials.
1418 MockWrite data_writes2[] = {
1419 MockWrite("GET / HTTP/1.1\r\n"
1420 "Host: www.google.com\r\n"
1421 "Connection: keep-alive\r\n"
1422 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1423 };
1424
1425 // Lastly, the server responds with the actual content.
1426 MockRead data_reads2[] = {
1427 MockRead("HTTP/1.1 200 OK\r\n"),
1428 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501429 MockRead("Content-Length: 5\r\n\r\n"),
1430 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311431 };
1432
[email protected]31a2bfe2010-02-09 08:03:391433 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1434 data_writes1, arraysize(data_writes1));
1435 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1436 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311437 session_deps.socket_factory.AddSocketDataProvider(&data1);
1438 session_deps.socket_factory.AddSocketDataProvider(&data2);
1439
1440 TestCompletionCallback callback1;
1441
[email protected]0b0bf032010-09-21 18:08:501442 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271443 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311444 EXPECT_EQ(ERR_IO_PENDING, rv);
1445
1446 rv = callback1.WaitForResult();
1447 EXPECT_EQ(OK, rv);
1448
1449 const HttpResponseInfo* response = trans->GetResponseInfo();
1450 EXPECT_FALSE(response == NULL);
1451
1452 // The password prompt info should have been set in response->auth_challenge.
1453 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1454
1455 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1456 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1457 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1458
1459 TestCompletionCallback callback2;
1460
[email protected]13c8a092010-07-29 06:15:441461 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311462 EXPECT_EQ(ERR_IO_PENDING, rv);
1463
1464 rv = callback2.WaitForResult();
1465 EXPECT_EQ(OK, rv);
1466
1467 response = trans->GetResponseInfo();
1468 ASSERT_FALSE(response == NULL);
1469 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501470 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311471}
1472
[email protected]394816e92010-08-03 07:38:591473// Test the request-challenge-retry sequence for basic auth, over a connection
1474// that requires a restart when setting up an SSL tunnel.
1475TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
[email protected]394816e92010-08-03 07:38:591476 HttpRequestInfo request;
1477 request.method = "GET";
1478 request.url = GURL("https://www.google.com/");
1479 // when the no authentication data flag is set.
1480 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1481
[email protected]cb9bf6ca2011-01-28 13:15:271482 // Configure against proxy server "myproxy:70".
1483 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1484 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1485 session_deps.net_log = log.bound().net_log();
1486 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1487
[email protected]394816e92010-08-03 07:38:591488 // Since we have proxy, should try to establish tunnel.
1489 MockWrite data_writes1[] = {
1490 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1491 "Host: www.google.com\r\n"
1492 "Proxy-Connection: keep-alive\r\n\r\n"),
1493
1494 // After calling trans->RestartWithAuth(), this is the request we should
1495 // be issuing -- the final header line contains the credentials.
1496 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1497 "Host: www.google.com\r\n"
1498 "Proxy-Connection: keep-alive\r\n"
1499 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1500
1501 MockWrite("GET / HTTP/1.1\r\n"
1502 "Host: www.google.com\r\n"
1503 "Connection: keep-alive\r\n\r\n"),
1504 };
1505
1506 // The proxy responds to the connect with a 407, using a persistent
1507 // connection.
1508 MockRead data_reads1[] = {
1509 // No credentials.
1510 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1511 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1512 MockRead("Proxy-Connection: close\r\n\r\n"),
1513
1514 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1515
1516 MockRead("HTTP/1.1 200 OK\r\n"),
1517 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501518 MockRead("Content-Length: 5\r\n\r\n"),
1519 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591520 };
1521
1522 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1523 data_writes1, arraysize(data_writes1));
1524 session_deps.socket_factory.AddSocketDataProvider(&data1);
1525 SSLSocketDataProvider ssl(true, OK);
1526 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1527
1528 TestCompletionCallback callback1;
1529
[email protected]0b0bf032010-09-21 18:08:501530 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1531
[email protected]394816e92010-08-03 07:38:591532 int rv = trans->Start(&request, &callback1, log.bound());
1533 EXPECT_EQ(ERR_IO_PENDING, rv);
1534
1535 rv = callback1.WaitForResult();
1536 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401537 net::CapturingNetLog::EntryList entries;
1538 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:591539 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401540 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:591541 NetLog::PHASE_NONE);
1542 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401543 entries, pos,
[email protected]394816e92010-08-03 07:38:591544 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1545 NetLog::PHASE_NONE);
1546
1547 const HttpResponseInfo* response = trans->GetResponseInfo();
1548 ASSERT_FALSE(response == NULL);
1549
1550 EXPECT_EQ(407, response->headers->response_code());
1551 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1552
1553 // The password prompt info should have been set in response->auth_challenge.
1554 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1555
1556 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1557 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1558 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1559
1560 TestCompletionCallback callback2;
1561
1562 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1563 EXPECT_EQ(ERR_IO_PENDING, rv);
1564
1565 rv = callback2.WaitForResult();
1566 EXPECT_EQ(OK, rv);
1567
1568 response = trans->GetResponseInfo();
1569 ASSERT_FALSE(response == NULL);
1570
1571 EXPECT_TRUE(response->headers->IsKeepAlive());
1572 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501573 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591574 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1575
1576 // The password prompt info should not be set.
1577 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501578
1579 trans.reset();
1580 session->FlushSocketPools();
[email protected]394816e92010-08-03 07:38:591581}
1582
[email protected]11203f012009-11-12 23:02:311583// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321584// proxy connection, when setting up an SSL tunnel.
1585TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
[email protected]cb9bf6ca2011-01-28 13:15:271586 HttpRequestInfo request;
1587 request.method = "GET";
1588 request.url = GURL("https://www.google.com/");
1589 // Ensure that proxy authentication is attempted even
1590 // when the no authentication data flag is set.
1591 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1592
[email protected]2d2697f92009-02-18 21:00:321593 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001594 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541595 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1596 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591597 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321598
[email protected]5695b8c2009-09-30 21:36:431599 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321600
[email protected]2d2697f92009-02-18 21:00:321601 // Since we have proxy, should try to establish tunnel.
1602 MockWrite data_writes1[] = {
1603 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451604 "Host: www.google.com\r\n"
1605 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321606
1607 // After calling trans->RestartWithAuth(), this is the request we should
1608 // be issuing -- the final header line contains the credentials.
1609 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1610 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451611 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321612 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1613 };
1614
1615 // The proxy responds to the connect with a 407, using a persistent
1616 // connection.
1617 MockRead data_reads1[] = {
1618 // No credentials.
1619 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1620 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1621 MockRead("Content-Length: 10\r\n\r\n"),
1622 MockRead("0123456789"),
1623
1624 // Wrong credentials (wrong password).
1625 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1626 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1627 MockRead("Content-Length: 10\r\n\r\n"),
1628 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421629 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321630 };
1631
[email protected]31a2bfe2010-02-09 08:03:391632 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1633 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591634 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321635
1636 TestCompletionCallback callback1;
1637
[email protected]dbb83db2010-05-11 18:13:391638 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421639 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321640
1641 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421642 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401643 net::CapturingNetLog::EntryList entries;
1644 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:391645 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401646 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:391647 NetLog::PHASE_NONE);
1648 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401649 entries, pos,
[email protected]dbb83db2010-05-11 18:13:391650 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1651 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321652
[email protected]1c773ea12009-04-28 19:58:421653 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321654 EXPECT_FALSE(response == NULL);
1655
1656 EXPECT_TRUE(response->headers->IsKeepAlive());
1657 EXPECT_EQ(407, response->headers->response_code());
1658 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421659 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321660
1661 // The password prompt info should have been set in response->auth_challenge.
1662 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1663
[email protected]71e4573a2009-05-21 22:03:001664 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321665 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1666 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1667
1668 TestCompletionCallback callback2;
1669
1670 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441671 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421672 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321673
1674 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421675 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321676
1677 response = trans->GetResponseInfo();
1678 EXPECT_FALSE(response == NULL);
1679
1680 EXPECT_TRUE(response->headers->IsKeepAlive());
1681 EXPECT_EQ(407, response->headers->response_code());
1682 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421683 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321684
1685 // The password prompt info should have been set in response->auth_challenge.
1686 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1687
[email protected]71e4573a2009-05-21 22:03:001688 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321689 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1690 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131691
[email protected]e60e47a2010-07-14 03:37:181692 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1693 // out of scope.
1694 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321695}
1696
[email protected]a8e9b162009-03-12 00:06:441697// Test that we don't read the response body when we fail to establish a tunnel,
1698// even if the user cancels the proxy's auth attempt.
1699TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:271700 HttpRequestInfo request;
1701 request.method = "GET";
1702 request.url = GURL("https://www.google.com/");
1703 request.load_flags = 0;
1704
[email protected]a8e9b162009-03-12 00:06:441705 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001706 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441707
[email protected]e44de5d2009-06-05 20:12:451708 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441709
[email protected]5695b8c2009-09-30 21:36:431710 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441711
[email protected]a8e9b162009-03-12 00:06:441712 // Since we have proxy, should try to establish tunnel.
1713 MockWrite data_writes[] = {
1714 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451715 "Host: www.google.com\r\n"
1716 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441717 };
1718
1719 // The proxy responds to the connect with a 407.
1720 MockRead data_reads[] = {
1721 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1722 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1723 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421724 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441725 };
1726
[email protected]31a2bfe2010-02-09 08:03:391727 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1728 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591729 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441730
1731 TestCompletionCallback callback;
1732
[email protected]5a1d7ca2010-04-28 20:12:271733 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421734 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441735
1736 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421737 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441738
[email protected]1c773ea12009-04-28 19:58:421739 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441740 EXPECT_FALSE(response == NULL);
1741
1742 EXPECT_TRUE(response->headers->IsKeepAlive());
1743 EXPECT_EQ(407, response->headers->response_code());
1744 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421745 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441746
1747 std::string response_data;
1748 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421749 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181750
1751 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1752 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441753}
1754
[email protected]8fdbcd22010-05-05 02:54:521755// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1756// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1757TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:521758 HttpRequestInfo request;
1759 request.method = "GET";
1760 request.url = GURL("http://www.google.com/");
1761 request.load_flags = 0;
1762
[email protected]cb9bf6ca2011-01-28 13:15:271763 // We are using a DIRECT connection (i.e. no proxy) for this session.
1764 SessionDependencies session_deps;
1765 scoped_ptr<HttpTransaction> trans(
1766 new HttpNetworkTransaction(CreateSession(&session_deps)));
1767
[email protected]8fdbcd22010-05-05 02:54:521768 MockWrite data_writes1[] = {
1769 MockWrite("GET / HTTP/1.1\r\n"
1770 "Host: www.google.com\r\n"
1771 "Connection: keep-alive\r\n\r\n"),
1772 };
1773
1774 MockRead data_reads1[] = {
1775 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1776 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1777 // Large content-length -- won't matter, as connection will be reset.
1778 MockRead("Content-Length: 10000\r\n\r\n"),
1779 MockRead(false, ERR_FAILED),
1780 };
1781
1782 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1783 data_writes1, arraysize(data_writes1));
1784 session_deps.socket_factory.AddSocketDataProvider(&data1);
1785
1786 TestCompletionCallback callback;
1787
1788 int rv = trans->Start(&request, &callback, BoundNetLog());
1789 EXPECT_EQ(ERR_IO_PENDING, rv);
1790
1791 rv = callback.WaitForResult();
1792 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1793}
1794
[email protected]7a67a8152010-11-05 18:31:101795// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
1796// through a non-authenticating proxy. The request should fail with
1797// ERR_UNEXPECTED_PROXY_AUTH.
1798// Note that it is impossible to detect if an HTTP server returns a 407 through
1799// a non-authenticating proxy - there is nothing to indicate whether the
1800// response came from the proxy or the server, so it is treated as if the proxy
1801// issued the challenge.
1802TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:271803 HttpRequestInfo request;
1804 request.method = "GET";
1805 request.url = GURL("https://www.google.com/");
1806
[email protected]7a67a8152010-11-05 18:31:101807 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1808 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1809 session_deps.net_log = log.bound().net_log();
1810 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1811
[email protected]7a67a8152010-11-05 18:31:101812 // Since we have proxy, should try to establish tunnel.
1813 MockWrite data_writes1[] = {
1814 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1815 "Host: www.google.com\r\n"
1816 "Proxy-Connection: keep-alive\r\n\r\n"),
1817
1818 MockWrite("GET / HTTP/1.1\r\n"
1819 "Host: www.google.com\r\n"
1820 "Connection: keep-alive\r\n\r\n"),
1821 };
1822
1823 MockRead data_reads1[] = {
1824 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1825
1826 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
1827 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1828 MockRead("\r\n"),
1829 MockRead(false, OK),
1830 };
1831
1832 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1833 data_writes1, arraysize(data_writes1));
1834 session_deps.socket_factory.AddSocketDataProvider(&data1);
1835 SSLSocketDataProvider ssl(true, OK);
1836 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1837
1838 TestCompletionCallback callback1;
1839
1840 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1841
1842 int rv = trans->Start(&request, &callback1, log.bound());
1843 EXPECT_EQ(ERR_IO_PENDING, rv);
1844
1845 rv = callback1.WaitForResult();
1846 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
[email protected]b2fcd0e2010-12-01 15:19:401847 net::CapturingNetLog::EntryList entries;
1848 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:101849 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401850 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:101851 NetLog::PHASE_NONE);
1852 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401853 entries, pos,
[email protected]7a67a8152010-11-05 18:31:101854 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1855 NetLog::PHASE_NONE);
1856}
[email protected]2df19bb2010-08-25 20:13:461857
1858// Test a simple get through an HTTPS Proxy.
1859TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271860 HttpRequestInfo request;
1861 request.method = "GET";
1862 request.url = GURL("http://www.google.com/");
1863
[email protected]2df19bb2010-08-25 20:13:461864 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001865 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:461866 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1867 session_deps.net_log = log.bound().net_log();
1868 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1869
[email protected]2df19bb2010-08-25 20:13:461870 // Since we have proxy, should use full url
1871 MockWrite data_writes1[] = {
1872 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1873 "Host: www.google.com\r\n"
1874 "Proxy-Connection: keep-alive\r\n\r\n"),
1875 };
1876
1877 MockRead data_reads1[] = {
1878 MockRead("HTTP/1.1 200 OK\r\n"),
1879 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1880 MockRead("Content-Length: 100\r\n\r\n"),
1881 MockRead(false, OK),
1882 };
1883
1884 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1885 data_writes1, arraysize(data_writes1));
1886 session_deps.socket_factory.AddSocketDataProvider(&data1);
1887 SSLSocketDataProvider ssl(true, OK);
1888 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1889
1890 TestCompletionCallback callback1;
1891
[email protected]0b0bf032010-09-21 18:08:501892 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1893
[email protected]2df19bb2010-08-25 20:13:461894 int rv = trans->Start(&request, &callback1, log.bound());
1895 EXPECT_EQ(ERR_IO_PENDING, rv);
1896
1897 rv = callback1.WaitForResult();
1898 EXPECT_EQ(OK, rv);
1899
1900 const HttpResponseInfo* response = trans->GetResponseInfo();
1901 ASSERT_FALSE(response == NULL);
1902
1903 EXPECT_TRUE(response->headers->IsKeepAlive());
1904 EXPECT_EQ(200, response->headers->response_code());
1905 EXPECT_EQ(100, response->headers->GetContentLength());
1906 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1907
1908 // The password prompt info should not be set.
1909 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1910}
1911
[email protected]7642b5ae2010-09-01 20:55:171912// Test a SPDY get through an HTTPS Proxy.
1913TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271914 HttpRequestInfo request;
1915 request.method = "GET";
1916 request.url = GURL("http://www.google.com/");
1917 request.load_flags = 0;
1918
[email protected]7642b5ae2010-09-01 20:55:171919 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001920 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:171921 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1922 session_deps.net_log = log.bound().net_log();
1923 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1924
[email protected]7642b5ae2010-09-01 20:55:171925 // fetch http://www.google.com/ via SPDY
1926 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1927 false));
1928 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1929
1930 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1931 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1932 MockRead spdy_reads[] = {
1933 CreateMockRead(*resp),
1934 CreateMockRead(*data),
1935 MockRead(true, 0, 0),
1936 };
1937
1938 scoped_refptr<DelayedSocketData> spdy_data(
1939 new DelayedSocketData(
1940 1, // wait for one write to finish before reading.
1941 spdy_reads, arraysize(spdy_reads),
1942 spdy_writes, arraysize(spdy_writes)));
1943 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1944
1945 SSLSocketDataProvider ssl(true, OK);
1946 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1947 ssl.next_proto = "spdy/2";
1948 ssl.was_npn_negotiated = true;
1949 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1950
1951 TestCompletionCallback callback1;
1952
[email protected]0b0bf032010-09-21 18:08:501953 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1954
[email protected]7642b5ae2010-09-01 20:55:171955 int rv = trans->Start(&request, &callback1, log.bound());
1956 EXPECT_EQ(ERR_IO_PENDING, rv);
1957
1958 rv = callback1.WaitForResult();
1959 EXPECT_EQ(OK, rv);
1960
1961 const HttpResponseInfo* response = trans->GetResponseInfo();
1962 ASSERT_TRUE(response != NULL);
1963 ASSERT_TRUE(response->headers != NULL);
1964 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1965
1966 std::string response_data;
1967 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1968 EXPECT_EQ(net::kUploadData, response_data);
1969}
1970
[email protected]dc7bd1c52010-11-12 00:01:131971// Test a SPDY get through an HTTPS Proxy.
1972TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:271973 HttpRequestInfo request;
1974 request.method = "GET";
1975 request.url = GURL("http://www.google.com/");
1976 request.load_flags = 0;
1977
[email protected]dc7bd1c52010-11-12 00:01:131978 // Configure against https proxy server "proxy:70".
1979 SessionDependencies session_deps(
1980 ProxyService::CreateFixed("https://proxy:70"));
1981 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1982 session_deps.net_log = log.bound().net_log();
1983 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1984
[email protected]dc7bd1c52010-11-12 00:01:131985 // The first request will be a bare GET, the second request will be a
1986 // GET with a Proxy-Authorization header.
1987 scoped_ptr<spdy::SpdyFrame> req_get(
1988 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
1989 const char* const kExtraAuthorizationHeaders[] = {
1990 "proxy-authorization",
1991 "Basic Zm9vOmJhcg==",
1992 };
1993 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
1994 ConstructSpdyGet(
1995 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
1996 false, 3, LOWEST, false));
1997 MockWrite spdy_writes[] = {
1998 CreateMockWrite(*req_get, 1),
1999 CreateMockWrite(*req_get_authorization, 4),
2000 };
2001
2002 // The first response is a 407 proxy authentication challenge, and the second
2003 // response will be a 200 response since the second request includes a valid
2004 // Authorization header.
2005 const char* const kExtraAuthenticationHeaders[] = {
2006 "Proxy-Authenticate",
2007 "Basic realm=\"MyRealm1\""
2008 };
2009 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2010 ConstructSpdySynReplyError(
2011 "407 Proxy Authentication Required",
2012 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2013 1));
2014 scoped_ptr<spdy::SpdyFrame> body_authentication(
2015 ConstructSpdyBodyFrame(1, true));
2016 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2017 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2018 MockRead spdy_reads[] = {
2019 CreateMockRead(*resp_authentication, 2),
2020 CreateMockRead(*body_authentication, 3),
2021 CreateMockRead(*resp_data, 5),
2022 CreateMockRead(*body_data, 6),
2023 MockRead(true, 0, 7),
2024 };
2025
2026 scoped_refptr<OrderedSocketData> data(
2027 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2028 spdy_writes, arraysize(spdy_writes)));
2029 session_deps.socket_factory.AddSocketDataProvider(data);
2030
2031 SSLSocketDataProvider ssl(true, OK);
2032 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2033 ssl.next_proto = "spdy/2";
2034 ssl.was_npn_negotiated = true;
2035 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2036
2037 TestCompletionCallback callback1;
2038
2039 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2040
2041 int rv = trans->Start(&request, &callback1, log.bound());
2042 EXPECT_EQ(ERR_IO_PENDING, rv);
2043
2044 rv = callback1.WaitForResult();
2045 EXPECT_EQ(OK, rv);
2046
2047 const HttpResponseInfo* const response = trans->GetResponseInfo();
2048
2049 ASSERT_TRUE(response != NULL);
2050 ASSERT_TRUE(response->headers != NULL);
2051 EXPECT_EQ(407, response->headers->response_code());
2052 EXPECT_TRUE(response->was_fetched_via_spdy);
2053
2054 // The password prompt info should have been set in response->auth_challenge.
2055 ASSERT_TRUE(response->auth_challenge.get() != NULL);
2056 EXPECT_TRUE(response->auth_challenge->is_proxy);
2057 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2058 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2059 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2060
2061 TestCompletionCallback callback2;
2062
2063 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2064 EXPECT_EQ(ERR_IO_PENDING, rv);
2065
2066 rv = callback2.WaitForResult();
2067 EXPECT_EQ(OK, rv);
2068
2069 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2070
2071 ASSERT_TRUE(response_restart != NULL);
2072 ASSERT_TRUE(response_restart->headers != NULL);
2073 EXPECT_EQ(200, response_restart->headers->response_code());
2074 // The password prompt info should not be set.
2075 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2076}
2077
[email protected]d9da5fe2010-10-13 22:37:162078// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2079TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272080 HttpRequestInfo request;
2081 request.method = "GET";
2082 request.url = GURL("https://www.google.com/");
2083 request.load_flags = 0;
2084
[email protected]d9da5fe2010-10-13 22:37:162085 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002086 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162087 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2088 session_deps.net_log = log.bound().net_log();
2089 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2090
2091 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2092
[email protected]d9da5fe2010-10-13 22:37:162093 // CONNECT to www.google.com:443 via SPDY
2094 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2095 // fetch https://www.google.com/ via HTTP
2096
2097 const char get[] = "GET / HTTP/1.1\r\n"
2098 "Host: www.google.com\r\n"
2099 "Connection: keep-alive\r\n\r\n";
2100 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2101 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2102 MockWrite spdy_writes[] = {
2103 CreateMockWrite(*connect, 1),
2104 CreateMockWrite(*wrapped_get, 3)
2105 };
2106
2107 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2108 const char resp[] = "HTTP/1.1 200 OK\r\n"
2109 "Content-Length: 10\r\n\r\n";
2110
2111 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2112 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2113 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2114 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2115 MockRead spdy_reads[] = {
2116 CreateMockRead(*conn_resp, 2, true),
2117 CreateMockRead(*wrapped_get_resp, 4, true),
2118 CreateMockRead(*wrapped_body, 5, true),
2119 CreateMockRead(*wrapped_body, 6, true),
2120 MockRead(true, 0, 7),
2121 };
2122
2123 scoped_refptr<OrderedSocketData> spdy_data(
2124 new OrderedSocketData(
2125 spdy_reads, arraysize(spdy_reads),
2126 spdy_writes, arraysize(spdy_writes)));
2127 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2128
2129 SSLSocketDataProvider ssl(true, OK);
2130 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2131 ssl.next_proto = "spdy/2";
2132 ssl.was_npn_negotiated = true;
2133 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2134 SSLSocketDataProvider ssl2(true, OK);
2135 ssl2.was_npn_negotiated = false;
2136 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2137
2138 TestCompletionCallback callback1;
2139
2140 int rv = trans->Start(&request, &callback1, log.bound());
2141 EXPECT_EQ(ERR_IO_PENDING, rv);
2142
2143 rv = callback1.WaitForResult();
2144 EXPECT_EQ(OK, rv);
2145
2146 const HttpResponseInfo* response = trans->GetResponseInfo();
2147 ASSERT_TRUE(response != NULL);
2148 ASSERT_TRUE(response->headers != NULL);
2149 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2150
2151 std::string response_data;
2152 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2153 EXPECT_EQ("1234567890", response_data);
2154}
2155
2156// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2157TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272158 HttpRequestInfo request;
2159 request.method = "GET";
2160 request.url = GURL("https://www.google.com/");
2161 request.load_flags = 0;
2162
[email protected]d9da5fe2010-10-13 22:37:162163 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002164 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162165 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2166 session_deps.net_log = log.bound().net_log();
2167 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2168
2169 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2170
[email protected]d9da5fe2010-10-13 22:37:162171 // CONNECT to www.google.com:443 via SPDY
2172 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2173 // fetch https://www.google.com/ via SPDY
2174 const char* const kMyUrl = "https://www.google.com/";
2175 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2176 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2177 MockWrite spdy_writes[] = {
2178 CreateMockWrite(*connect, 1),
2179 CreateMockWrite(*wrapped_get, 3)
2180 };
2181
2182 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2183 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2184 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2185 ConstructWrappedSpdyFrame(get_resp, 1));
2186 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2187 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2188 MockRead spdy_reads[] = {
2189 CreateMockRead(*conn_resp, 2, true),
2190 CreateMockRead(*wrapped_get_resp, 4, true),
2191 CreateMockRead(*wrapped_body, 5, true),
2192 MockRead(true, 0, 1),
2193 };
2194
2195 scoped_refptr<OrderedSocketData> spdy_data(
2196 new OrderedSocketData(
2197 spdy_reads, arraysize(spdy_reads),
2198 spdy_writes, arraysize(spdy_writes)));
2199 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2200
2201 SSLSocketDataProvider ssl(true, OK);
2202 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2203 ssl.next_proto = "spdy/2";
2204 ssl.was_npn_negotiated = true;
2205 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2206 SSLSocketDataProvider ssl2(true, OK);
2207 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2208 ssl2.next_proto = "spdy/2";
2209 ssl2.was_npn_negotiated = true;
2210 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2211
2212 TestCompletionCallback callback1;
2213
2214 int rv = trans->Start(&request, &callback1, log.bound());
2215 EXPECT_EQ(ERR_IO_PENDING, rv);
2216
2217 rv = callback1.WaitForResult();
2218 EXPECT_EQ(OK, rv);
2219
2220 const HttpResponseInfo* response = trans->GetResponseInfo();
2221 ASSERT_TRUE(response != NULL);
2222 ASSERT_TRUE(response->headers != NULL);
2223 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2224
2225 std::string response_data;
2226 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2227 EXPECT_EQ(net::kUploadData, response_data);
2228}
2229
2230// Test a SPDY CONNECT failure through an HTTPS Proxy.
2231TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272232 HttpRequestInfo request;
2233 request.method = "GET";
2234 request.url = GURL("https://www.google.com/");
2235 request.load_flags = 0;
2236
[email protected]d9da5fe2010-10-13 22:37:162237 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002238 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162239 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2240 session_deps.net_log = log.bound().net_log();
2241 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2242
2243 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2244
[email protected]d9da5fe2010-10-13 22:37:162245 // CONNECT to www.google.com:443 via SPDY
2246 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2247 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2248
2249 MockWrite spdy_writes[] = {
2250 CreateMockWrite(*connect, 1),
2251 CreateMockWrite(*get, 3),
2252 };
2253
2254 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2255 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2256 MockRead spdy_reads[] = {
2257 CreateMockRead(*resp, 2, true),
2258 MockRead(true, 0, 4),
2259 };
2260
2261 scoped_refptr<OrderedSocketData> spdy_data(
2262 new OrderedSocketData(
2263 spdy_reads, arraysize(spdy_reads),
2264 spdy_writes, arraysize(spdy_writes)));
2265 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2266
2267 SSLSocketDataProvider ssl(true, OK);
2268 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2269 ssl.next_proto = "spdy/2";
2270 ssl.was_npn_negotiated = true;
2271 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2272 SSLSocketDataProvider ssl2(true, OK);
2273 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2274 ssl2.next_proto = "spdy/2";
2275 ssl2.was_npn_negotiated = true;
2276 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2277
2278 TestCompletionCallback callback1;
2279
2280 int rv = trans->Start(&request, &callback1, log.bound());
2281 EXPECT_EQ(ERR_IO_PENDING, rv);
2282
2283 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292284 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162285
2286 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]511f6f52010-12-17 03:58:292287 ASSERT_FALSE(response == NULL);
2288 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162289}
2290
[email protected]2df19bb2010-08-25 20:13:462291// Test the challenge-response-retry sequence through an HTTPS Proxy
2292TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462293 HttpRequestInfo request;
2294 request.method = "GET";
2295 request.url = GURL("http://www.google.com/");
2296 // when the no authentication data flag is set.
2297 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2298
[email protected]cb9bf6ca2011-01-28 13:15:272299 // Configure against https proxy server "proxy:70".
2300 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
2301 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2302 session_deps.net_log = log.bound().net_log();
2303 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2304
[email protected]2df19bb2010-08-25 20:13:462305 // Since we have proxy, should use full url
2306 MockWrite data_writes1[] = {
2307 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2308 "Host: www.google.com\r\n"
2309 "Proxy-Connection: keep-alive\r\n\r\n"),
2310
2311 // After calling trans->RestartWithAuth(), this is the request we should
2312 // be issuing -- the final header line contains the credentials.
2313 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2314 "Host: www.google.com\r\n"
2315 "Proxy-Connection: keep-alive\r\n"
2316 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2317 };
2318
2319 // The proxy responds to the GET with a 407, using a persistent
2320 // connection.
2321 MockRead data_reads1[] = {
2322 // No credentials.
2323 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2324 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2325 MockRead("Proxy-Connection: keep-alive\r\n"),
2326 MockRead("Content-Length: 0\r\n\r\n"),
2327
2328 MockRead("HTTP/1.1 200 OK\r\n"),
2329 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2330 MockRead("Content-Length: 100\r\n\r\n"),
2331 MockRead(false, OK),
2332 };
2333
2334 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2335 data_writes1, arraysize(data_writes1));
2336 session_deps.socket_factory.AddSocketDataProvider(&data1);
2337 SSLSocketDataProvider ssl(true, OK);
2338 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2339
2340 TestCompletionCallback callback1;
2341
[email protected]0b0bf032010-09-21 18:08:502342 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2343
[email protected]2df19bb2010-08-25 20:13:462344 int rv = trans->Start(&request, &callback1, log.bound());
2345 EXPECT_EQ(ERR_IO_PENDING, rv);
2346
2347 rv = callback1.WaitForResult();
2348 EXPECT_EQ(OK, rv);
2349
2350 const HttpResponseInfo* response = trans->GetResponseInfo();
2351 ASSERT_FALSE(response == NULL);
2352
2353 EXPECT_EQ(407, response->headers->response_code());
2354 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2355
2356 // The password prompt info should have been set in response->auth_challenge.
2357 ASSERT_FALSE(response->auth_challenge.get() == NULL);
2358
2359 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2360 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2361 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2362
2363 TestCompletionCallback callback2;
2364
2365 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2366 EXPECT_EQ(ERR_IO_PENDING, rv);
2367
2368 rv = callback2.WaitForResult();
2369 EXPECT_EQ(OK, rv);
2370
2371 response = trans->GetResponseInfo();
2372 ASSERT_FALSE(response == NULL);
2373
2374 EXPECT_TRUE(response->headers->IsKeepAlive());
2375 EXPECT_EQ(200, response->headers->response_code());
2376 EXPECT_EQ(100, response->headers->GetContentLength());
2377 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2378
2379 // The password prompt info should not be set.
2380 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2381}
2382
[email protected]ff007e162009-05-23 09:13:152383void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082384 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422385 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082386 request.method = "GET";
2387 request.url = GURL("https://www.google.com/");
2388 request.load_flags = 0;
2389
[email protected]cb9bf6ca2011-01-28 13:15:272390 // Configure against proxy server "myproxy:70".
2391 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2392
2393 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2394
[email protected]c744cf22009-02-27 07:28:082395 // Since we have proxy, should try to establish tunnel.
2396 MockWrite data_writes[] = {
2397 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452398 "Host: www.google.com\r\n"
2399 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082400 };
2401
2402 MockRead data_reads[] = {
2403 status,
2404 MockRead("Content-Length: 10\r\n\r\n"),
2405 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422406 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082407 };
2408
[email protected]31a2bfe2010-02-09 08:03:392409 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2410 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592411 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082412
2413 TestCompletionCallback callback;
2414
[email protected]0b0bf032010-09-21 18:08:502415 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2416
[email protected]5a1d7ca2010-04-28 20:12:272417 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422418 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082419
2420 rv = callback.WaitForResult();
2421 EXPECT_EQ(expected_status, rv);
2422}
2423
[email protected]ff007e162009-05-23 09:13:152424void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082425 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422426 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082427}
2428
2429TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2430 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2431}
2432
2433TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2434 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2435}
2436
2437TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2438 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2439}
2440
2441TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2442 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2443}
2444
2445TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2446 ConnectStatusHelper(
2447 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2448}
2449
2450TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2451 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2452}
2453
2454TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2455 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2456}
2457
2458TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2459 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2460}
2461
2462TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2463 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2464}
2465
2466TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2467 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2468}
2469
2470TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2471 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2472}
2473
2474TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2475 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2476}
2477
2478TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2479 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2480}
2481
2482TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2483 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2484}
2485
2486TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2487 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2488}
2489
2490TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2491 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2492}
2493
2494TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2495 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2496}
2497
2498TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2499 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2500}
2501
2502TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2503 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2504}
2505
2506TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2507 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2508}
2509
2510TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2511 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2512}
2513
2514TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2515 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2516}
2517
2518TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2519 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2520}
2521
2522TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2523 ConnectStatusHelperWithExpectedStatus(
2524 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542525 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082526}
2527
2528TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2529 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2530}
2531
2532TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2533 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2534}
2535
2536TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2537 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2538}
2539
2540TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2541 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2542}
2543
2544TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2545 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2546}
2547
2548TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2549 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2550}
2551
2552TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2553 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2554}
2555
2556TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2557 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2558}
2559
2560TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2561 ConnectStatusHelper(
2562 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2563}
2564
2565TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2566 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2567}
2568
2569TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2570 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2571}
2572
2573TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2574 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2575}
2576
2577TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2578 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2579}
2580
2581TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2582 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2583}
2584
2585TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2586 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2587}
2588
2589TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2590 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2591}
2592
[email protected]038e9a32008-10-08 22:40:162593// Test the flow when both the proxy server AND origin server require
2594// authentication. Again, this uses basic auth for both since that is
2595// the simplest to mock.
2596TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272597 HttpRequestInfo request;
2598 request.method = "GET";
2599 request.url = GURL("http://www.google.com/");
2600 request.load_flags = 0;
2601
[email protected]81cdfcd2010-10-16 00:49:002602 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012603
[email protected]038e9a32008-10-08 22:40:162604 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422605 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432606 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162607
[email protected]f9ee6b52008-11-08 06:46:232608 MockWrite data_writes1[] = {
2609 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2610 "Host: www.google.com\r\n"
2611 "Proxy-Connection: keep-alive\r\n\r\n"),
2612 };
2613
[email protected]038e9a32008-10-08 22:40:162614 MockRead data_reads1[] = {
2615 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2616 // Give a couple authenticate options (only the middle one is actually
2617 // supported).
[email protected]22927ad2009-09-21 19:56:192618 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162619 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2620 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2621 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2622 // Large content-length -- won't matter, as connection will be reset.
2623 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422624 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162625 };
2626
2627 // After calling trans->RestartWithAuth() the first time, this is the
2628 // request we should be issuing -- the final header line contains the
2629 // proxy's credentials.
2630 MockWrite data_writes2[] = {
2631 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2632 "Host: www.google.com\r\n"
2633 "Proxy-Connection: keep-alive\r\n"
2634 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2635 };
2636
2637 // Now the proxy server lets the request pass through to origin server.
2638 // The origin server responds with a 401.
2639 MockRead data_reads2[] = {
2640 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2641 // Note: We are using the same realm-name as the proxy server. This is
2642 // completely valid, as realms are unique across hosts.
2643 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2644 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2645 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422646 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162647 };
2648
2649 // After calling trans->RestartWithAuth() the second time, we should send
2650 // the credentials for both the proxy and origin server.
2651 MockWrite data_writes3[] = {
2652 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2653 "Host: www.google.com\r\n"
2654 "Proxy-Connection: keep-alive\r\n"
2655 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2656 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2657 };
2658
2659 // Lastly we get the desired content.
2660 MockRead data_reads3[] = {
2661 MockRead("HTTP/1.0 200 OK\r\n"),
2662 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2663 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422664 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162665 };
2666
[email protected]31a2bfe2010-02-09 08:03:392667 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2668 data_writes1, arraysize(data_writes1));
2669 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2670 data_writes2, arraysize(data_writes2));
2671 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2672 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592673 session_deps.socket_factory.AddSocketDataProvider(&data1);
2674 session_deps.socket_factory.AddSocketDataProvider(&data2);
2675 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162676
2677 TestCompletionCallback callback1;
2678
[email protected]5a1d7ca2010-04-28 20:12:272679 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422680 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162681
2682 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422683 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162684
[email protected]1c773ea12009-04-28 19:58:422685 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162686 EXPECT_FALSE(response == NULL);
2687
2688 // The password prompt info should have been set in response->auth_challenge.
2689 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2690
[email protected]71e4573a2009-05-21 22:03:002691 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162692 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2693 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2694
2695 TestCompletionCallback callback2;
2696
[email protected]13c8a092010-07-29 06:15:442697 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422698 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162699
2700 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422701 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162702
2703 response = trans->GetResponseInfo();
2704 EXPECT_FALSE(response == NULL);
2705 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2706
[email protected]71e4573a2009-05-21 22:03:002707 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162708 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2709 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2710
2711 TestCompletionCallback callback3;
2712
[email protected]13c8a092010-07-29 06:15:442713 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422714 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162715
2716 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422717 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162718
2719 response = trans->GetResponseInfo();
2720 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2721 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162722}
[email protected]4ddaf2502008-10-23 18:26:192723
[email protected]ea9dc9a2009-09-05 00:43:322724// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2725// can't hook into its internals to cause it to generate predictable NTLM
2726// authorization headers.
2727#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292728// The NTLM authentication unit tests were generated by capturing the HTTP
2729// requests and responses using Fiddler 2 and inspecting the generated random
2730// bytes in the debugger.
2731
2732// Enter the correct password and authenticate successfully.
2733TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422734 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242735 request.method = "GET";
2736 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2737 request.load_flags = 0;
2738
[email protected]cb9bf6ca2011-01-28 13:15:272739 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2740 MockGetHostName);
2741 SessionDependencies session_deps;
2742 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2743
[email protected]3f918782009-02-28 01:29:242744 MockWrite data_writes1[] = {
2745 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2746 "Host: 172.22.68.17\r\n"
2747 "Connection: keep-alive\r\n\r\n"),
2748 };
2749
2750 MockRead data_reads1[] = {
2751 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042752 // Negotiate and NTLM are often requested together. However, we only want
2753 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2754 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242755 MockRead("WWW-Authenticate: NTLM\r\n"),
2756 MockRead("Connection: close\r\n"),
2757 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362758 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242759 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422760 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242761 };
2762
2763 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222764 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242765 // request we should be issuing -- the final header line contains a Type
2766 // 1 message.
2767 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2768 "Host: 172.22.68.17\r\n"
2769 "Connection: keep-alive\r\n"
2770 "Authorization: NTLM "
2771 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2772
2773 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2774 // (the credentials for the origin server). The second request continues
2775 // on the same connection.
2776 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2777 "Host: 172.22.68.17\r\n"
2778 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292779 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2780 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2781 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2782 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2783 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242784 };
2785
2786 MockRead data_reads2[] = {
2787 // The origin server responds with a Type 2 message.
2788 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2789 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292790 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242791 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2792 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2793 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2794 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2795 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2796 "BtAAAAAAA=\r\n"),
2797 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362798 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242799 MockRead("You are not authorized to view this page\r\n"),
2800
2801 // Lastly we get the desired content.
2802 MockRead("HTTP/1.1 200 OK\r\n"),
2803 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2804 MockRead("Content-Length: 13\r\n\r\n"),
2805 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422806 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242807 };
2808
[email protected]31a2bfe2010-02-09 08:03:392809 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2810 data_writes1, arraysize(data_writes1));
2811 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2812 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592813 session_deps.socket_factory.AddSocketDataProvider(&data1);
2814 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242815
2816 TestCompletionCallback callback1;
2817
[email protected]0b0bf032010-09-21 18:08:502818 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2819
[email protected]5a1d7ca2010-04-28 20:12:272820 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422821 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242822
2823 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422824 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242825
[email protected]0757e7702009-03-27 04:00:222826 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2827 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442828 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422829 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222830 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422831 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222832 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2833
[email protected]1c773ea12009-04-28 19:58:422834 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042835 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242836
[email protected]aef04272010-06-28 18:03:042837 // The password prompt info should have been set in
2838 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242839 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2840
[email protected]71e4573a2009-05-21 22:03:002841 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242842 EXPECT_EQ(L"", response->auth_challenge->realm);
2843 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2844
[email protected]0757e7702009-03-27 04:00:222845 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242846
[email protected]13c8a092010-07-29 06:15:442847 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422848 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242849
[email protected]0757e7702009-03-27 04:00:222850 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422851 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242852
2853 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042854 ASSERT_FALSE(response == NULL);
2855
[email protected]3f918782009-02-28 01:29:242856 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2857 EXPECT_EQ(13, response->headers->GetContentLength());
2858}
2859
[email protected]385a4672009-03-11 22:21:292860// Enter a wrong password, and then the correct one.
2861TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422862 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292863 request.method = "GET";
2864 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2865 request.load_flags = 0;
2866
[email protected]cb9bf6ca2011-01-28 13:15:272867 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
2868 MockGetHostName);
2869 SessionDependencies session_deps;
2870 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2871
[email protected]385a4672009-03-11 22:21:292872 MockWrite data_writes1[] = {
2873 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2874 "Host: 172.22.68.17\r\n"
2875 "Connection: keep-alive\r\n\r\n"),
2876 };
2877
2878 MockRead data_reads1[] = {
2879 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042880 // Negotiate and NTLM are often requested together. However, we only want
2881 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2882 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292883 MockRead("WWW-Authenticate: NTLM\r\n"),
2884 MockRead("Connection: close\r\n"),
2885 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362886 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292887 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422888 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292889 };
2890
2891 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222892 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292893 // request we should be issuing -- the final header line contains a Type
2894 // 1 message.
2895 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2896 "Host: 172.22.68.17\r\n"
2897 "Connection: keep-alive\r\n"
2898 "Authorization: NTLM "
2899 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2900
2901 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2902 // (the credentials for the origin server). The second request continues
2903 // on the same connection.
2904 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2905 "Host: 172.22.68.17\r\n"
2906 "Connection: keep-alive\r\n"
2907 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2908 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2909 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2910 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2911 "4Ww7b7E=\r\n\r\n"),
2912 };
2913
2914 MockRead data_reads2[] = {
2915 // The origin server responds with a Type 2 message.
2916 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2917 MockRead("WWW-Authenticate: NTLM "
2918 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2919 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2920 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2921 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2922 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2923 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2924 "BtAAAAAAA=\r\n"),
2925 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362926 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292927 MockRead("You are not authorized to view this page\r\n"),
2928
2929 // Wrong password.
2930 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292931 MockRead("WWW-Authenticate: NTLM\r\n"),
2932 MockRead("Connection: close\r\n"),
2933 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362934 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292935 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422936 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292937 };
2938
2939 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222940 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292941 // request we should be issuing -- the final header line contains a Type
2942 // 1 message.
2943 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2944 "Host: 172.22.68.17\r\n"
2945 "Connection: keep-alive\r\n"
2946 "Authorization: NTLM "
2947 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2948
2949 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2950 // (the credentials for the origin server). The second request continues
2951 // on the same connection.
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"
2955 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2956 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2957 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2958 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2959 "+4MUm7c=\r\n\r\n"),
2960 };
2961
2962 MockRead data_reads3[] = {
2963 // The origin server responds with a Type 2 message.
2964 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2965 MockRead("WWW-Authenticate: NTLM "
2966 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2967 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2968 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2969 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2970 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2971 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2972 "BtAAAAAAA=\r\n"),
2973 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362974 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292975 MockRead("You are not authorized to view this page\r\n"),
2976
2977 // Lastly we get the desired content.
2978 MockRead("HTTP/1.1 200 OK\r\n"),
2979 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2980 MockRead("Content-Length: 13\r\n\r\n"),
2981 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422982 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292983 };
2984
[email protected]31a2bfe2010-02-09 08:03:392985 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2986 data_writes1, arraysize(data_writes1));
2987 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2988 data_writes2, arraysize(data_writes2));
2989 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2990 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592991 session_deps.socket_factory.AddSocketDataProvider(&data1);
2992 session_deps.socket_factory.AddSocketDataProvider(&data2);
2993 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292994
2995 TestCompletionCallback callback1;
2996
[email protected]0b0bf032010-09-21 18:08:502997 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2998
[email protected]5a1d7ca2010-04-28 20:12:272999 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423000 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293001
3002 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423003 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293004
[email protected]0757e7702009-03-27 04:00:223005 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293006 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443007 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423008 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293009 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423010 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223011 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293012
[email protected]1c773ea12009-04-28 19:58:423013 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:293014 EXPECT_FALSE(response == NULL);
3015
3016 // The password prompt info should have been set in response->auth_challenge.
3017 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3018
[email protected]71e4573a2009-05-21 22:03:003019 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:293020 EXPECT_EQ(L"", response->auth_challenge->realm);
3021 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3022
3023 TestCompletionCallback callback3;
3024
[email protected]0757e7702009-03-27 04:00:223025 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:443026 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:423027 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293028
3029 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423030 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293031
[email protected]0757e7702009-03-27 04:00:223032 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3033 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:443034 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:423035 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223036 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423037 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223038 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3039
3040 response = trans->GetResponseInfo();
3041 EXPECT_FALSE(response == NULL);
3042
3043 // The password prompt info should have been set in response->auth_challenge.
3044 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3045
[email protected]71e4573a2009-05-21 22:03:003046 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:223047 EXPECT_EQ(L"", response->auth_challenge->realm);
3048 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3049
3050 TestCompletionCallback callback5;
3051
3052 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:443053 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:423054 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223055
3056 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423057 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223058
[email protected]385a4672009-03-11 22:21:293059 response = trans->GetResponseInfo();
3060 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3061 EXPECT_EQ(13, response->headers->GetContentLength());
3062}
[email protected]ea9dc9a2009-09-05 00:43:323063#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293064
[email protected]4ddaf2502008-10-23 18:26:193065// Test reading a server response which has only headers, and no body.
3066// After some maximum number of bytes is consumed, the transaction should
3067// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3068TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423069 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193070 request.method = "GET";
3071 request.url = GURL("http://www.google.com/");
3072 request.load_flags = 0;
3073
[email protected]cb9bf6ca2011-01-28 13:15:273074 SessionDependencies session_deps;
3075 scoped_ptr<HttpTransaction> trans(
3076 new HttpNetworkTransaction(CreateSession(&session_deps)));
3077
[email protected]b75b7b2f2009-10-06 00:54:533078 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433079 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533080 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193081
3082 MockRead data_reads[] = {
3083 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433084 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193085 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423086 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193087 };
[email protected]31a2bfe2010-02-09 08:03:393088 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593089 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193090
3091 TestCompletionCallback callback;
3092
[email protected]5a1d7ca2010-04-28 20:12:273093 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423094 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193095
3096 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423097 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193098
[email protected]1c773ea12009-04-28 19:58:423099 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193100 EXPECT_TRUE(response == NULL);
3101}
[email protected]f4e426b2008-11-05 00:24:493102
3103// Make sure that we don't try to reuse a TCPClientSocket when failing to
3104// establish tunnel.
3105// http://code.google.com/p/chromium/issues/detail?id=3772
3106TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273107 HttpRequestInfo request;
3108 request.method = "GET";
3109 request.url = GURL("https://www.google.com/");
3110 request.load_flags = 0;
3111
[email protected]f4e426b2008-11-05 00:24:493112 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003113 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013114
[email protected]228ff742009-06-05 01:19:593115 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493116
[email protected]5695b8c2009-09-30 21:36:433117 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493118
[email protected]f4e426b2008-11-05 00:24:493119 // Since we have proxy, should try to establish tunnel.
3120 MockWrite data_writes1[] = {
3121 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453122 "Host: www.google.com\r\n"
3123 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493124 };
3125
[email protected]77848d12008-11-14 00:00:223126 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493127 // connection. Usually a proxy would return 501 (not implemented),
3128 // or 200 (tunnel established).
3129 MockRead data_reads1[] = {
3130 MockRead("HTTP/1.1 404 Not Found\r\n"),
3131 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423132 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493133 };
3134
[email protected]31a2bfe2010-02-09 08:03:393135 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3136 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593137 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493138
3139 TestCompletionCallback callback1;
3140
[email protected]5a1d7ca2010-04-28 20:12:273141 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423142 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493143
3144 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423145 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493146
[email protected]1c773ea12009-04-28 19:58:423147 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083148 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493149
[email protected]b4404c02009-04-10 16:38:523150 // Empty the current queue. This is necessary because idle sockets are
3151 // added to the connection pool asynchronously with a PostTask.
3152 MessageLoop::current()->RunAllPending();
3153
[email protected]f4e426b2008-11-05 00:24:493154 // We now check to make sure the TCPClientSocket was not added back to
3155 // the pool.
[email protected]a937a06d2009-08-19 21:19:243156 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493157 trans.reset();
[email protected]b4404c02009-04-10 16:38:523158 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493159 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:243160 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493161}
[email protected]372d34a2008-11-05 21:30:513162
[email protected]1b157c02009-04-21 01:55:403163// Make sure that we recycle a socket after reading all of the response body.
3164TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423165 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403166 request.method = "GET";
3167 request.url = GURL("http://www.google.com/");
3168 request.load_flags = 0;
3169
[email protected]cb9bf6ca2011-01-28 13:15:273170 SessionDependencies session_deps;
3171 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3172
3173 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3174
[email protected]1b157c02009-04-21 01:55:403175 MockRead data_reads[] = {
3176 // A part of the response body is received with the response headers.
3177 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3178 // The rest of the response body is received in two parts.
3179 MockRead("lo"),
3180 MockRead(" world"),
3181 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423182 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403183 };
3184
[email protected]31a2bfe2010-02-09 08:03:393185 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593186 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403187
3188 TestCompletionCallback callback;
3189
[email protected]5a1d7ca2010-04-28 20:12:273190 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423191 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403192
3193 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423194 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403195
[email protected]1c773ea12009-04-28 19:58:423196 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:403197 EXPECT_TRUE(response != NULL);
3198
3199 EXPECT_TRUE(response->headers != NULL);
3200 std::string status_line = response->headers->GetStatusLine();
3201 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3202
[email protected]a937a06d2009-08-19 21:19:243203 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403204
3205 std::string response_data;
3206 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423207 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403208 EXPECT_EQ("hello world", response_data);
3209
3210 // Empty the current queue. This is necessary because idle sockets are
3211 // added to the connection pool asynchronously with a PostTask.
3212 MessageLoop::current()->RunAllPending();
3213
3214 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243215 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403216}
3217
[email protected]76a505b2010-08-25 06:23:003218// Make sure that we recycle a SSL socket after reading all of the response
3219// body.
3220TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3221 SessionDependencies session_deps;
3222 HttpRequestInfo request;
3223 request.method = "GET";
3224 request.url = GURL("https://www.google.com/");
3225 request.load_flags = 0;
3226
3227 MockWrite data_writes[] = {
3228 MockWrite("GET / HTTP/1.1\r\n"
3229 "Host: www.google.com\r\n"
3230 "Connection: keep-alive\r\n\r\n"),
3231 };
3232
3233 MockRead data_reads[] = {
3234 MockRead("HTTP/1.1 200 OK\r\n"),
3235 MockRead("Content-Length: 11\r\n\r\n"),
3236 MockRead("hello world"),
3237 MockRead(false, OK),
3238 };
3239
3240 SSLSocketDataProvider ssl(true, OK);
3241 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3242
3243 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3244 data_writes, arraysize(data_writes));
3245 session_deps.socket_factory.AddSocketDataProvider(&data);
3246
3247 TestCompletionCallback callback;
3248
3249 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3250 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3251
3252 int rv = trans->Start(&request, &callback, BoundNetLog());
3253
3254 EXPECT_EQ(ERR_IO_PENDING, rv);
3255 EXPECT_EQ(OK, callback.WaitForResult());
3256
3257 const HttpResponseInfo* response = trans->GetResponseInfo();
3258 ASSERT_TRUE(response != NULL);
3259 ASSERT_TRUE(response->headers != NULL);
3260 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3261
3262 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3263
3264 std::string response_data;
3265 rv = ReadTransaction(trans.get(), &response_data);
3266 EXPECT_EQ(OK, rv);
3267 EXPECT_EQ("hello world", response_data);
3268
3269 // Empty the current queue. This is necessary because idle sockets are
3270 // added to the connection pool asynchronously with a PostTask.
3271 MessageLoop::current()->RunAllPending();
3272
3273 // We now check to make sure the socket was added back to the pool.
3274 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3275}
3276
3277// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3278// from the pool and make sure that we recover okay.
3279TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3280 SessionDependencies session_deps;
3281 HttpRequestInfo request;
3282 request.method = "GET";
3283 request.url = GURL("https://www.google.com/");
3284 request.load_flags = 0;
3285
3286 MockWrite data_writes[] = {
3287 MockWrite("GET / HTTP/1.1\r\n"
3288 "Host: www.google.com\r\n"
3289 "Connection: keep-alive\r\n\r\n"),
3290 MockWrite("GET / HTTP/1.1\r\n"
3291 "Host: www.google.com\r\n"
3292 "Connection: keep-alive\r\n\r\n"),
3293 };
3294
3295 MockRead data_reads[] = {
3296 MockRead("HTTP/1.1 200 OK\r\n"),
3297 MockRead("Content-Length: 11\r\n\r\n"),
3298 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3299 MockRead("hello world"),
3300 MockRead(true, 0, 0) // EOF
3301 };
3302
3303 SSLSocketDataProvider ssl(true, OK);
3304 SSLSocketDataProvider ssl2(true, OK);
3305 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3306 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3307
3308 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3309 data_writes, arraysize(data_writes));
3310 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3311 data_writes, arraysize(data_writes));
3312 session_deps.socket_factory.AddSocketDataProvider(&data);
3313 session_deps.socket_factory.AddSocketDataProvider(&data2);
3314
3315 TestCompletionCallback callback;
3316
3317 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3318 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3319
3320 int rv = trans->Start(&request, &callback, BoundNetLog());
3321
3322 EXPECT_EQ(ERR_IO_PENDING, rv);
3323 EXPECT_EQ(OK, callback.WaitForResult());
3324
3325 const HttpResponseInfo* response = trans->GetResponseInfo();
3326 ASSERT_TRUE(response != NULL);
3327 ASSERT_TRUE(response->headers != NULL);
3328 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3329
3330 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3331
3332 std::string response_data;
3333 rv = ReadTransaction(trans.get(), &response_data);
3334 EXPECT_EQ(OK, rv);
3335 EXPECT_EQ("hello world", response_data);
3336
3337 // Empty the current queue. This is necessary because idle sockets are
3338 // added to the connection pool asynchronously with a PostTask.
3339 MessageLoop::current()->RunAllPending();
3340
3341 // We now check to make sure the socket was added back to the pool.
3342 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3343
3344 // Now start the second transaction, which should reuse the previous socket.
3345
3346 trans.reset(new HttpNetworkTransaction(session));
3347
3348 rv = trans->Start(&request, &callback, BoundNetLog());
3349
3350 EXPECT_EQ(ERR_IO_PENDING, rv);
3351 EXPECT_EQ(OK, callback.WaitForResult());
3352
3353 response = trans->GetResponseInfo();
3354 ASSERT_TRUE(response != NULL);
3355 ASSERT_TRUE(response->headers != NULL);
3356 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3357
3358 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3359
3360 rv = ReadTransaction(trans.get(), &response_data);
3361 EXPECT_EQ(OK, rv);
3362 EXPECT_EQ("hello world", response_data);
3363
3364 // Empty the current queue. This is necessary because idle sockets are
3365 // added to the connection pool asynchronously with a PostTask.
3366 MessageLoop::current()->RunAllPending();
3367
3368 // We now check to make sure the socket was added back to the pool.
3369 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3370}
3371
[email protected]b4404c02009-04-10 16:38:523372// Make sure that we recycle a socket after a zero-length response.
3373// http://crbug.com/9880
3374TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423375 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523376 request.method = "GET";
3377 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3378 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3379 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3380 "rt=prt.2642,ol.2649,xjs.2951");
3381 request.load_flags = 0;
3382
[email protected]cb9bf6ca2011-01-28 13:15:273383 SessionDependencies session_deps;
3384 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3385
3386 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3387
[email protected]b4404c02009-04-10 16:38:523388 MockRead data_reads[] = {
3389 MockRead("HTTP/1.1 204 No Content\r\n"
3390 "Content-Length: 0\r\n"
3391 "Content-Type: text/html\r\n\r\n"),
3392 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423393 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523394 };
3395
[email protected]31a2bfe2010-02-09 08:03:393396 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593397 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523398
3399 TestCompletionCallback callback;
3400
[email protected]5a1d7ca2010-04-28 20:12:273401 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423402 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523403
3404 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423405 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523406
[email protected]1c773ea12009-04-28 19:58:423407 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523408 EXPECT_TRUE(response != NULL);
3409
3410 EXPECT_TRUE(response->headers != NULL);
3411 std::string status_line = response->headers->GetStatusLine();
3412 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3413
[email protected]a937a06d2009-08-19 21:19:243414 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523415
3416 std::string response_data;
3417 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423418 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523419 EXPECT_EQ("", 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.
[email protected]a937a06d2009-08-19 21:19:243426 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523427}
3428
[email protected]372d34a2008-11-05 21:30:513429TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423430 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513431 // Transaction 1: a GET request that succeeds. The socket is recycled
3432 // after use.
3433 request[0].method = "GET";
3434 request[0].url = GURL("http://www.google.com/");
3435 request[0].load_flags = 0;
3436 // Transaction 2: a POST request. Reuses the socket kept alive from
3437 // transaction 1. The first attempts fails when writing the POST data.
3438 // This causes the transaction to retry with a new socket. The second
3439 // attempt succeeds.
3440 request[1].method = "POST";
3441 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423442 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513443 request[1].upload_data->AppendBytes("foo", 3);
3444 request[1].load_flags = 0;
3445
[email protected]228ff742009-06-05 01:19:593446 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273447 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513448
3449 // The first socket is used for transaction 1 and the first attempt of
3450 // transaction 2.
3451
3452 // The response of transaction 1.
3453 MockRead data_reads1[] = {
3454 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3455 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423456 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513457 };
3458 // The mock write results of transaction 1 and the first attempt of
3459 // transaction 2.
3460 MockWrite data_writes1[] = {
3461 MockWrite(false, 64), // GET
3462 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423463 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513464 };
[email protected]31a2bfe2010-02-09 08:03:393465 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3466 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513467
3468 // The second socket is used for the second attempt of transaction 2.
3469
3470 // The response of transaction 2.
3471 MockRead data_reads2[] = {
3472 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3473 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423474 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513475 };
3476 // The mock write results of the second attempt of transaction 2.
3477 MockWrite data_writes2[] = {
3478 MockWrite(false, 93), // POST
3479 MockWrite(false, 3), // POST data
3480 };
[email protected]31a2bfe2010-02-09 08:03:393481 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3482 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513483
[email protected]5ecc992a42009-11-11 01:41:593484 session_deps.socket_factory.AddSocketDataProvider(&data1);
3485 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513486
3487 const char* kExpectedResponseData[] = {
3488 "hello world", "welcome"
3489 };
3490
3491 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423492 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433493 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513494
3495 TestCompletionCallback callback;
3496
[email protected]5a1d7ca2010-04-28 20:12:273497 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423498 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513499
3500 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423501 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513502
[email protected]1c773ea12009-04-28 19:58:423503 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513504 EXPECT_TRUE(response != NULL);
3505
3506 EXPECT_TRUE(response->headers != NULL);
3507 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3508
3509 std::string response_data;
3510 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423511 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513512 EXPECT_EQ(kExpectedResponseData[i], response_data);
3513 }
3514}
[email protected]f9ee6b52008-11-08 06:46:233515
3516// Test the request-challenge-retry sequence for basic auth when there is
3517// an identity in the URL. The request should be sent as normal, but when
3518// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323519TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423520 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233521 request.method = "GET";
3522 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293523 request.url = GURL("http://foo:b@[email protected]/");
3524
[email protected]cb9bf6ca2011-01-28 13:15:273525 SessionDependencies session_deps;
3526 scoped_ptr<HttpTransaction> trans(
3527 new HttpNetworkTransaction(CreateSession(&session_deps)));
3528
[email protected]a97cca42009-08-14 01:00:293529 // The password contains an escaped character -- for this test to pass it
3530 // will need to be unescaped by HttpNetworkTransaction.
3531 EXPECT_EQ("b%40r", request.url.password());
3532
[email protected]ea9dc9a2009-09-05 00:43:323533 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233534
3535 MockWrite data_writes1[] = {
3536 MockWrite("GET / HTTP/1.1\r\n"
3537 "Host: www.google.com\r\n"
3538 "Connection: keep-alive\r\n\r\n"),
3539 };
3540
3541 MockRead data_reads1[] = {
3542 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3543 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3544 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423545 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233546 };
3547
3548 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323549 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233550 MockWrite data_writes2[] = {
3551 MockWrite("GET / HTTP/1.1\r\n"
3552 "Host: www.google.com\r\n"
3553 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293554 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233555 };
3556
3557 MockRead data_reads2[] = {
3558 MockRead("HTTP/1.0 200 OK\r\n"),
3559 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423560 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233561 };
3562
[email protected]31a2bfe2010-02-09 08:03:393563 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3564 data_writes1, arraysize(data_writes1));
3565 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3566 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593567 session_deps.socket_factory.AddSocketDataProvider(&data1);
3568 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233569
3570 TestCompletionCallback callback1;
3571
[email protected]5a1d7ca2010-04-28 20:12:273572 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423573 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233574
3575 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423576 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233577
[email protected]0757e7702009-03-27 04:00:223578 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3579 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443580 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423581 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223582 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423583 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223584 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3585
[email protected]1c773ea12009-04-28 19:58:423586 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233587 EXPECT_FALSE(response == NULL);
3588
3589 // There is no challenge info, since the identity in URL worked.
3590 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3591
3592 EXPECT_EQ(100, response->headers->GetContentLength());
3593
3594 // Empty the current queue.
3595 MessageLoop::current()->RunAllPending();
3596}
3597
[email protected]ea9dc9a2009-09-05 00:43:323598// Test the request-challenge-retry sequence for basic auth when there is
3599// an incorrect identity in the URL. The identity from the URL should be used
3600// only once.
3601TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]ea9dc9a2009-09-05 00:43:323602 HttpRequestInfo request;
3603 request.method = "GET";
3604 // Note: the URL has a username:password in it. The password "baz" is
3605 // wrong (should be "bar").
3606 request.url = GURL("http://foo:[email protected]/");
3607
3608 request.load_flags = LOAD_NORMAL;
3609
[email protected]cb9bf6ca2011-01-28 13:15:273610 SessionDependencies session_deps;
3611 scoped_ptr<HttpTransaction> trans(
3612 new HttpNetworkTransaction(CreateSession(&session_deps)));
3613
[email protected]ea9dc9a2009-09-05 00:43:323614 MockWrite data_writes1[] = {
3615 MockWrite("GET / HTTP/1.1\r\n"
3616 "Host: www.google.com\r\n"
3617 "Connection: keep-alive\r\n\r\n"),
3618 };
3619
3620 MockRead data_reads1[] = {
3621 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3622 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3623 MockRead("Content-Length: 10\r\n\r\n"),
3624 MockRead(false, ERR_FAILED),
3625 };
3626
3627 // After the challenge above, the transaction will be restarted using the
3628 // identity from the url (foo, baz) to answer the challenge.
3629 MockWrite data_writes2[] = {
3630 MockWrite("GET / HTTP/1.1\r\n"
3631 "Host: www.google.com\r\n"
3632 "Connection: keep-alive\r\n"
3633 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3634 };
3635
3636 MockRead data_reads2[] = {
3637 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3638 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3639 MockRead("Content-Length: 10\r\n\r\n"),
3640 MockRead(false, ERR_FAILED),
3641 };
3642
3643 // After the challenge above, the transaction will be restarted using the
3644 // identity supplied by the user (foo, bar) to answer the challenge.
3645 MockWrite data_writes3[] = {
3646 MockWrite("GET / HTTP/1.1\r\n"
3647 "Host: www.google.com\r\n"
3648 "Connection: keep-alive\r\n"
3649 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3650 };
3651
3652 MockRead data_reads3[] = {
3653 MockRead("HTTP/1.0 200 OK\r\n"),
3654 MockRead("Content-Length: 100\r\n\r\n"),
3655 MockRead(false, OK),
3656 };
3657
[email protected]31a2bfe2010-02-09 08:03:393658 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3659 data_writes1, arraysize(data_writes1));
3660 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3661 data_writes2, arraysize(data_writes2));
3662 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3663 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593664 session_deps.socket_factory.AddSocketDataProvider(&data1);
3665 session_deps.socket_factory.AddSocketDataProvider(&data2);
3666 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323667
3668 TestCompletionCallback callback1;
3669
[email protected]5a1d7ca2010-04-28 20:12:273670 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323671 EXPECT_EQ(ERR_IO_PENDING, rv);
3672
3673 rv = callback1.WaitForResult();
3674 EXPECT_EQ(OK, rv);
3675
3676 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3677 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443678 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323679 EXPECT_EQ(ERR_IO_PENDING, rv);
3680 rv = callback2.WaitForResult();
3681 EXPECT_EQ(OK, rv);
3682 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3683
3684 const HttpResponseInfo* response = trans->GetResponseInfo();
3685 EXPECT_FALSE(response == NULL);
3686 // The password prompt info should have been set in response->auth_challenge.
3687 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3688
3689 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3690 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3691 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3692
3693 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443694 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323695 EXPECT_EQ(ERR_IO_PENDING, rv);
3696 rv = callback3.WaitForResult();
3697 EXPECT_EQ(OK, rv);
3698 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3699
3700 response = trans->GetResponseInfo();
3701 EXPECT_FALSE(response == NULL);
3702
3703 // There is no challenge info, since the identity worked.
3704 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3705
3706 EXPECT_EQ(100, response->headers->GetContentLength());
3707
3708 // Empty the current queue.
3709 MessageLoop::current()->RunAllPending();
3710}
3711
[email protected]f9ee6b52008-11-08 06:46:233712// Test that previously tried username/passwords for a realm get re-used.
3713TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593714 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273715 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233716
3717 // Transaction 1: authenticate (foo, bar) on MyRealm1
3718 {
[email protected]1c773ea12009-04-28 19:58:423719 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233720 request.method = "GET";
3721 request.url = GURL("http://www.google.com/x/y/z");
3722 request.load_flags = 0;
3723
[email protected]cb9bf6ca2011-01-28 13:15:273724 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3725
[email protected]f9ee6b52008-11-08 06:46:233726 MockWrite data_writes1[] = {
3727 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3728 "Host: www.google.com\r\n"
3729 "Connection: keep-alive\r\n\r\n"),
3730 };
3731
3732 MockRead data_reads1[] = {
3733 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3734 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3735 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423736 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233737 };
3738
3739 // Resend with authorization (username=foo, password=bar)
3740 MockWrite data_writes2[] = {
3741 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3742 "Host: www.google.com\r\n"
3743 "Connection: keep-alive\r\n"
3744 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3745 };
3746
3747 // Sever accepts the authorization.
3748 MockRead data_reads2[] = {
3749 MockRead("HTTP/1.0 200 OK\r\n"),
3750 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423751 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233752 };
3753
[email protected]31a2bfe2010-02-09 08:03:393754 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3755 data_writes1, arraysize(data_writes1));
3756 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3757 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593758 session_deps.socket_factory.AddSocketDataProvider(&data1);
3759 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233760
3761 TestCompletionCallback callback1;
3762
[email protected]5a1d7ca2010-04-28 20:12:273763 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423764 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233765
3766 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423767 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233768
[email protected]1c773ea12009-04-28 19:58:423769 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233770 EXPECT_FALSE(response == NULL);
3771
3772 // The password prompt info should have been set in
3773 // response->auth_challenge.
3774 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3775
[email protected]71e4573a2009-05-21 22:03:003776 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233777 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3778 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3779
3780 TestCompletionCallback callback2;
3781
[email protected]13c8a092010-07-29 06:15:443782 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423783 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233784
3785 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423786 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233787
3788 response = trans->GetResponseInfo();
3789 EXPECT_FALSE(response == NULL);
3790 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3791 EXPECT_EQ(100, response->headers->GetContentLength());
3792 }
3793
3794 // ------------------------------------------------------------------------
3795
3796 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3797 {
[email protected]1c773ea12009-04-28 19:58:423798 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233799 request.method = "GET";
3800 // Note that Transaction 1 was at /x/y/z, so this is in the same
3801 // protection space as MyRealm1.
3802 request.url = GURL("http://www.google.com/x/y/a/b");
3803 request.load_flags = 0;
3804
[email protected]cb9bf6ca2011-01-28 13:15:273805 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3806
[email protected]f9ee6b52008-11-08 06:46:233807 MockWrite data_writes1[] = {
3808 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3809 "Host: www.google.com\r\n"
3810 "Connection: keep-alive\r\n"
3811 // Send preemptive authorization for MyRealm1
3812 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3813 };
3814
3815 // The server didn't like the preemptive authorization, and
3816 // challenges us for a different realm (MyRealm2).
3817 MockRead data_reads1[] = {
3818 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3819 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3820 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423821 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233822 };
3823
3824 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3825 MockWrite data_writes2[] = {
3826 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3827 "Host: www.google.com\r\n"
3828 "Connection: keep-alive\r\n"
3829 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3830 };
3831
3832 // Sever accepts the authorization.
3833 MockRead data_reads2[] = {
3834 MockRead("HTTP/1.0 200 OK\r\n"),
3835 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423836 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233837 };
3838
[email protected]31a2bfe2010-02-09 08:03:393839 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3840 data_writes1, arraysize(data_writes1));
3841 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3842 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593843 session_deps.socket_factory.AddSocketDataProvider(&data1);
3844 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233845
3846 TestCompletionCallback callback1;
3847
[email protected]5a1d7ca2010-04-28 20:12:273848 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423849 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233850
3851 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423852 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233853
[email protected]1c773ea12009-04-28 19:58:423854 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233855 EXPECT_FALSE(response == NULL);
3856
3857 // The password prompt info should have been set in
3858 // response->auth_challenge.
3859 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3860
[email protected]71e4573a2009-05-21 22:03:003861 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233862 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3863 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3864
3865 TestCompletionCallback callback2;
3866
[email protected]13c8a092010-07-29 06:15:443867 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423868 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233869
3870 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423871 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233872
3873 response = trans->GetResponseInfo();
3874 EXPECT_FALSE(response == NULL);
3875 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3876 EXPECT_EQ(100, response->headers->GetContentLength());
3877 }
3878
3879 // ------------------------------------------------------------------------
3880
3881 // Transaction 3: Resend a request in MyRealm's protection space --
3882 // succeed with preemptive authorization.
3883 {
[email protected]1c773ea12009-04-28 19:58:423884 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233885 request.method = "GET";
3886 request.url = GURL("http://www.google.com/x/y/z2");
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/z2 HTTP/1.1\r\n"
3893 "Host: www.google.com\r\n"
3894 "Connection: keep-alive\r\n"
3895 // The authorization for MyRealm1 gets sent preemptively
3896 // (since the url is in the same protection space)
3897 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3898 };
3899
3900 // Sever accepts the preemptive authorization
3901 MockRead data_reads1[] = {
3902 MockRead("HTTP/1.0 200 OK\r\n"),
3903 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423904 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233905 };
3906
[email protected]31a2bfe2010-02-09 08:03:393907 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3908 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593909 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233910
3911 TestCompletionCallback callback1;
3912
[email protected]5a1d7ca2010-04-28 20:12:273913 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423914 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233915
3916 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423917 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233918
[email protected]1c773ea12009-04-28 19:58:423919 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233920 EXPECT_FALSE(response == NULL);
3921
3922 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3923 EXPECT_EQ(100, response->headers->GetContentLength());
3924 }
3925
3926 // ------------------------------------------------------------------------
3927
3928 // Transaction 4: request another URL in MyRealm (however the
3929 // url is not known to belong to the protection space, so no pre-auth).
3930 {
[email protected]1c773ea12009-04-28 19:58:423931 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233932 request.method = "GET";
3933 request.url = GURL("http://www.google.com/x/1");
3934 request.load_flags = 0;
3935
[email protected]cb9bf6ca2011-01-28 13:15:273936 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3937
[email protected]f9ee6b52008-11-08 06:46:233938 MockWrite data_writes1[] = {
3939 MockWrite("GET /x/1 HTTP/1.1\r\n"
3940 "Host: www.google.com\r\n"
3941 "Connection: keep-alive\r\n\r\n"),
3942 };
3943
3944 MockRead data_reads1[] = {
3945 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3946 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3947 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423948 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233949 };
3950
3951 // Resend with authorization from MyRealm's cache.
3952 MockWrite data_writes2[] = {
3953 MockWrite("GET /x/1 HTTP/1.1\r\n"
3954 "Host: www.google.com\r\n"
3955 "Connection: keep-alive\r\n"
3956 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3957 };
3958
3959 // Sever accepts the authorization.
3960 MockRead data_reads2[] = {
3961 MockRead("HTTP/1.0 200 OK\r\n"),
3962 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423963 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233964 };
3965
[email protected]31a2bfe2010-02-09 08:03:393966 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3967 data_writes1, arraysize(data_writes1));
3968 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3969 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593970 session_deps.socket_factory.AddSocketDataProvider(&data1);
3971 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233972
3973 TestCompletionCallback callback1;
3974
[email protected]5a1d7ca2010-04-28 20:12:273975 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423976 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233977
3978 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423979 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233980
[email protected]0757e7702009-03-27 04:00:223981 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3982 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443983 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423984 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223985 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423986 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223987 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3988
[email protected]1c773ea12009-04-28 19:58:423989 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233990 EXPECT_FALSE(response == NULL);
3991 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3992 EXPECT_EQ(100, response->headers->GetContentLength());
3993 }
3994
3995 // ------------------------------------------------------------------------
3996
3997 // Transaction 5: request a URL in MyRealm, but the server rejects the
3998 // cached identity. Should invalidate and re-prompt.
3999 {
[email protected]1c773ea12009-04-28 19:58:424000 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234001 request.method = "GET";
4002 request.url = GURL("http://www.google.com/p/q/t");
4003 request.load_flags = 0;
4004
[email protected]cb9bf6ca2011-01-28 13:15:274005 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4006
[email protected]f9ee6b52008-11-08 06:46:234007 MockWrite data_writes1[] = {
4008 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4009 "Host: www.google.com\r\n"
4010 "Connection: keep-alive\r\n\r\n"),
4011 };
4012
4013 MockRead data_reads1[] = {
4014 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4015 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4016 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424017 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234018 };
4019
4020 // Resend with authorization from cache for MyRealm.
4021 MockWrite data_writes2[] = {
4022 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4023 "Host: www.google.com\r\n"
4024 "Connection: keep-alive\r\n"
4025 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4026 };
4027
4028 // Sever rejects the authorization.
4029 MockRead data_reads2[] = {
4030 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4031 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4032 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424033 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234034 };
4035
4036 // At this point we should prompt for new credentials for MyRealm.
4037 // Restart with username=foo3, password=foo4.
4038 MockWrite data_writes3[] = {
4039 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4040 "Host: www.google.com\r\n"
4041 "Connection: keep-alive\r\n"
4042 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4043 };
4044
4045 // Sever accepts the authorization.
4046 MockRead data_reads3[] = {
4047 MockRead("HTTP/1.0 200 OK\r\n"),
4048 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424049 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234050 };
4051
[email protected]31a2bfe2010-02-09 08:03:394052 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4053 data_writes1, arraysize(data_writes1));
4054 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4055 data_writes2, arraysize(data_writes2));
4056 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4057 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594058 session_deps.socket_factory.AddSocketDataProvider(&data1);
4059 session_deps.socket_factory.AddSocketDataProvider(&data2);
4060 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234061
4062 TestCompletionCallback callback1;
4063
[email protected]5a1d7ca2010-04-28 20:12:274064 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424065 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234066
4067 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424068 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234069
[email protected]0757e7702009-03-27 04:00:224070 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4071 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444072 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424073 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224074 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424075 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224076 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4077
[email protected]1c773ea12009-04-28 19:58:424078 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234079 EXPECT_FALSE(response == NULL);
4080
4081 // The password prompt info should have been set in
4082 // response->auth_challenge.
4083 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4084
[email protected]71e4573a2009-05-21 22:03:004085 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:234086 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4087 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4088
[email protected]0757e7702009-03-27 04:00:224089 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234090
[email protected]13c8a092010-07-29 06:15:444091 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:424092 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234093
[email protected]0757e7702009-03-27 04:00:224094 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424095 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234096
4097 response = trans->GetResponseInfo();
4098 EXPECT_FALSE(response == NULL);
4099 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4100 EXPECT_EQ(100, response->headers->GetContentLength());
4101 }
4102}
[email protected]89ceba9a2009-03-21 03:46:064103
[email protected]3c32c5f2010-05-18 15:18:124104// Tests that nonce count increments when multiple auth attempts
4105// are started with the same nonce.
4106TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4107 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444108 HttpAuthHandlerDigest::Factory* digest_factory =
4109 new HttpAuthHandlerDigest::Factory();
4110 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4111 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4112 digest_factory->set_nonce_generator(nonce_generator);
4113 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274114 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124115
4116 // Transaction 1: authenticate (foo, bar) on MyRealm1
4117 {
[email protected]3c32c5f2010-05-18 15:18:124118 HttpRequestInfo request;
4119 request.method = "GET";
4120 request.url = GURL("http://www.google.com/x/y/z");
4121 request.load_flags = 0;
4122
[email protected]cb9bf6ca2011-01-28 13:15:274123 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4124
[email protected]3c32c5f2010-05-18 15:18:124125 MockWrite data_writes1[] = {
4126 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4127 "Host: www.google.com\r\n"
4128 "Connection: keep-alive\r\n\r\n"),
4129 };
4130
4131 MockRead data_reads1[] = {
4132 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4133 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4134 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4135 MockRead(false, OK),
4136 };
4137
4138 // Resend with authorization (username=foo, password=bar)
4139 MockWrite data_writes2[] = {
4140 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4141 "Host: www.google.com\r\n"
4142 "Connection: keep-alive\r\n"
4143 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4144 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4145 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4146 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4147 };
4148
4149 // Sever accepts the authorization.
4150 MockRead data_reads2[] = {
4151 MockRead("HTTP/1.0 200 OK\r\n"),
4152 MockRead(false, OK),
4153 };
4154
4155 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4156 data_writes1, arraysize(data_writes1));
4157 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4158 data_writes2, arraysize(data_writes2));
4159 session_deps.socket_factory.AddSocketDataProvider(&data1);
4160 session_deps.socket_factory.AddSocketDataProvider(&data2);
4161
4162 TestCompletionCallback callback1;
4163
4164 int rv = trans->Start(&request, &callback1, BoundNetLog());
4165 EXPECT_EQ(ERR_IO_PENDING, rv);
4166
4167 rv = callback1.WaitForResult();
4168 EXPECT_EQ(OK, rv);
4169
4170 const HttpResponseInfo* response = trans->GetResponseInfo();
4171 ASSERT_FALSE(response == NULL);
4172
4173 // The password prompt info should have been set in
4174 // response->auth_challenge.
4175 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4176
4177 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4178 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
4179 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
4180
4181 TestCompletionCallback callback2;
4182
[email protected]13c8a092010-07-29 06:15:444183 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:124184 EXPECT_EQ(ERR_IO_PENDING, rv);
4185
4186 rv = callback2.WaitForResult();
4187 EXPECT_EQ(OK, rv);
4188
4189 response = trans->GetResponseInfo();
4190 ASSERT_FALSE(response == NULL);
4191 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4192 }
4193
4194 // ------------------------------------------------------------------------
4195
4196 // Transaction 2: Request another resource in digestive's protection space.
4197 // This will preemptively add an Authorization header which should have an
4198 // "nc" value of 2 (as compared to 1 in the first use.
4199 {
[email protected]3c32c5f2010-05-18 15:18:124200 HttpRequestInfo request;
4201 request.method = "GET";
4202 // Note that Transaction 1 was at /x/y/z, so this is in the same
4203 // protection space as digest.
4204 request.url = GURL("http://www.google.com/x/y/a/b");
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/a/b HTTP/1.1\r\n"
4211 "Host: www.google.com\r\n"
4212 "Connection: keep-alive\r\n"
4213 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4214 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4215 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4216 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4217 };
4218
4219 // Sever accepts the authorization.
4220 MockRead data_reads1[] = {
4221 MockRead("HTTP/1.0 200 OK\r\n"),
4222 MockRead("Content-Length: 100\r\n\r\n"),
4223 MockRead(false, OK),
4224 };
4225
4226 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4227 data_writes1, arraysize(data_writes1));
4228 session_deps.socket_factory.AddSocketDataProvider(&data1);
4229
4230 TestCompletionCallback callback1;
4231
4232 int rv = trans->Start(&request, &callback1, BoundNetLog());
4233 EXPECT_EQ(ERR_IO_PENDING, rv);
4234
4235 rv = callback1.WaitForResult();
4236 EXPECT_EQ(OK, rv);
4237
4238 const HttpResponseInfo* response = trans->GetResponseInfo();
4239 ASSERT_FALSE(response == NULL);
4240 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4241 }
4242}
4243
[email protected]89ceba9a2009-03-21 03:46:064244// Test the ResetStateForRestart() private method.
4245TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4246 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594247 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404248 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434249 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064250
4251 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064252 trans->read_buf_ = new IOBuffer(15);
4253 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204254 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064255
4256 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144257 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574258 response->auth_challenge = new AuthChallengeInfo();
4259 response->ssl_info.cert_status = -15;
4260 response->response_time = base::Time::Now();
4261 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064262
4263 { // Setup state for response_.vary_data
4264 HttpRequestInfo request;
4265 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4266 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274267 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434268 request.extra_headers.SetHeader("Foo", "1");
4269 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574270 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064271 }
4272
4273 // Cause the above state to be reset.
4274 trans->ResetStateForRestart();
4275
4276 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074277 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064278 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204279 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574280 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4281 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044282 EXPECT_FALSE(response->was_cached);
[email protected]0877e3d2009-10-17 22:29:574283 EXPECT_EQ(0, response->ssl_info.cert_status);
4284 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064285}
4286
[email protected]bacff652009-03-31 17:50:334287// Test HTTPS connections to a site with a bad certificate
4288TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334289 HttpRequestInfo request;
4290 request.method = "GET";
4291 request.url = GURL("https://www.google.com/");
4292 request.load_flags = 0;
4293
[email protected]cb9bf6ca2011-01-28 13:15:274294 SessionDependencies session_deps;
4295 scoped_ptr<HttpTransaction> trans(
4296 new HttpNetworkTransaction(CreateSession(&session_deps)));
4297
[email protected]bacff652009-03-31 17:50:334298 MockWrite data_writes[] = {
4299 MockWrite("GET / HTTP/1.1\r\n"
4300 "Host: www.google.com\r\n"
4301 "Connection: keep-alive\r\n\r\n"),
4302 };
4303
4304 MockRead data_reads[] = {
4305 MockRead("HTTP/1.0 200 OK\r\n"),
4306 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4307 MockRead("Content-Length: 100\r\n\r\n"),
4308 MockRead(false, OK),
4309 };
4310
[email protected]5ecc992a42009-11-11 01:41:594311 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394312 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4313 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594314 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4315 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334316
[email protected]5ecc992a42009-11-11 01:41:594317 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4318 session_deps.socket_factory.AddSocketDataProvider(&data);
4319 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4320 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334321
4322 TestCompletionCallback callback;
4323
[email protected]5a1d7ca2010-04-28 20:12:274324 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334325 EXPECT_EQ(ERR_IO_PENDING, rv);
4326
4327 rv = callback.WaitForResult();
4328 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4329
4330 rv = trans->RestartIgnoringLastError(&callback);
4331 EXPECT_EQ(ERR_IO_PENDING, rv);
4332
4333 rv = callback.WaitForResult();
4334 EXPECT_EQ(OK, rv);
4335
4336 const HttpResponseInfo* response = trans->GetResponseInfo();
4337
4338 EXPECT_FALSE(response == NULL);
4339 EXPECT_EQ(100, response->headers->GetContentLength());
4340}
4341
4342// Test HTTPS connections to a site with a bad certificate, going through a
4343// proxy
4344TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004345 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334346
4347 HttpRequestInfo request;
4348 request.method = "GET";
4349 request.url = GURL("https://www.google.com/");
4350 request.load_flags = 0;
4351
4352 MockWrite proxy_writes[] = {
4353 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454354 "Host: www.google.com\r\n"
4355 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334356 };
4357
4358 MockRead proxy_reads[] = {
4359 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424360 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334361 };
4362
4363 MockWrite data_writes[] = {
4364 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454365 "Host: www.google.com\r\n"
4366 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334367 MockWrite("GET / HTTP/1.1\r\n"
4368 "Host: www.google.com\r\n"
4369 "Connection: keep-alive\r\n\r\n"),
4370 };
4371
4372 MockRead data_reads[] = {
4373 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4374 MockRead("HTTP/1.0 200 OK\r\n"),
4375 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4376 MockRead("Content-Length: 100\r\n\r\n"),
4377 MockRead(false, OK),
4378 };
4379
[email protected]31a2bfe2010-02-09 08:03:394380 StaticSocketDataProvider ssl_bad_certificate(
4381 proxy_reads, arraysize(proxy_reads),
4382 proxy_writes, arraysize(proxy_writes));
4383 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4384 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594385 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4386 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334387
[email protected]5ecc992a42009-11-11 01:41:594388 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4389 session_deps.socket_factory.AddSocketDataProvider(&data);
4390 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4391 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334392
4393 TestCompletionCallback callback;
4394
4395 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594396 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334397
[email protected]d207a5f2009-06-04 05:28:404398 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434399 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334400
[email protected]5a1d7ca2010-04-28 20:12:274401 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334402 EXPECT_EQ(ERR_IO_PENDING, rv);
4403
4404 rv = callback.WaitForResult();
4405 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4406
4407 rv = trans->RestartIgnoringLastError(&callback);
4408 EXPECT_EQ(ERR_IO_PENDING, rv);
4409
4410 rv = callback.WaitForResult();
4411 EXPECT_EQ(OK, rv);
4412
4413 const HttpResponseInfo* response = trans->GetResponseInfo();
4414
4415 EXPECT_FALSE(response == NULL);
4416 EXPECT_EQ(100, response->headers->GetContentLength());
4417 }
4418}
4419
[email protected]2df19bb2010-08-25 20:13:464420
4421// Test HTTPS connections to a site, going through an HTTPS proxy
4422TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004423 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464424
4425 HttpRequestInfo request;
4426 request.method = "GET";
4427 request.url = GURL("https://www.google.com/");
4428 request.load_flags = 0;
4429
4430 MockWrite data_writes[] = {
4431 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4432 "Host: www.google.com\r\n"
4433 "Proxy-Connection: keep-alive\r\n\r\n"),
4434 MockWrite("GET / HTTP/1.1\r\n"
4435 "Host: www.google.com\r\n"
4436 "Connection: keep-alive\r\n\r\n"),
4437 };
4438
4439 MockRead data_reads[] = {
4440 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4441 MockRead("HTTP/1.1 200 OK\r\n"),
4442 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4443 MockRead("Content-Length: 100\r\n\r\n"),
4444 MockRead(false, OK),
4445 };
4446
4447 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4448 data_writes, arraysize(data_writes));
4449 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4450 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4451
4452 session_deps.socket_factory.AddSocketDataProvider(&data);
4453 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4454 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4455
4456 TestCompletionCallback callback;
4457
4458 scoped_ptr<HttpTransaction> trans(
4459 new HttpNetworkTransaction(CreateSession(&session_deps)));
4460
4461 int rv = trans->Start(&request, &callback, BoundNetLog());
4462 EXPECT_EQ(ERR_IO_PENDING, rv);
4463
4464 rv = callback.WaitForResult();
4465 EXPECT_EQ(OK, rv);
4466 const HttpResponseInfo* response = trans->GetResponseInfo();
4467
4468 ASSERT_FALSE(response == NULL);
4469
4470 EXPECT_TRUE(response->headers->IsKeepAlive());
4471 EXPECT_EQ(200, response->headers->response_code());
4472 EXPECT_EQ(100, response->headers->GetContentLength());
4473 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4474}
4475
[email protected]511f6f52010-12-17 03:58:294476// Test an HTTPS Proxy's ability to redirect a CONNECT request
4477TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4478 SessionDependencies session_deps(
4479 ProxyService::CreateFixed("https://proxy:70"));
4480
4481 HttpRequestInfo request;
4482 request.method = "GET";
4483 request.url = GURL("https://www.google.com/");
4484 request.load_flags = 0;
4485
4486 MockWrite data_writes[] = {
4487 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4488 "Host: www.google.com\r\n"
4489 "Proxy-Connection: keep-alive\r\n\r\n"),
4490 };
4491
4492 MockRead data_reads[] = {
4493 MockRead("HTTP/1.1 302 Redirect\r\n"),
4494 MockRead("Location: http://login.example.com/\r\n"),
4495 MockRead("Content-Length: 0\r\n\r\n"),
4496 MockRead(false, OK),
4497 };
4498
4499 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4500 data_writes, arraysize(data_writes));
4501 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4502
4503 session_deps.socket_factory.AddSocketDataProvider(&data);
4504 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4505
4506 TestCompletionCallback callback;
4507
4508 scoped_ptr<HttpTransaction> trans(
4509 new HttpNetworkTransaction(CreateSession(&session_deps)));
4510
4511 int rv = trans->Start(&request, &callback, BoundNetLog());
4512 EXPECT_EQ(ERR_IO_PENDING, rv);
4513
4514 rv = callback.WaitForResult();
4515 EXPECT_EQ(OK, rv);
4516 const HttpResponseInfo* response = trans->GetResponseInfo();
4517
4518 ASSERT_FALSE(response == NULL);
4519
4520 EXPECT_EQ(302, response->headers->response_code());
4521 std::string url;
4522 EXPECT_TRUE(response->headers->IsRedirect(&url));
4523 EXPECT_EQ("http://login.example.com/", url);
4524}
4525
4526// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4527TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4528 SessionDependencies session_deps(
4529 ProxyService::CreateFixed("https://proxy:70"));
4530
4531 HttpRequestInfo request;
4532 request.method = "GET";
4533 request.url = GURL("https://www.google.com/");
4534 request.load_flags = 0;
4535
4536 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4537 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4538 MockWrite data_writes[] = {
4539 CreateMockWrite(*conn.get(), 0, false),
4540 };
4541
4542 static const char* const kExtraHeaders[] = {
4543 "location",
4544 "http://login.example.com/",
4545 };
4546 scoped_ptr<spdy::SpdyFrame> resp(
4547 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4548 arraysize(kExtraHeaders)/2, 1));
4549 MockRead data_reads[] = {
4550 CreateMockRead(*resp.get(), 1, false),
4551 MockRead(true, 0, 2), // EOF
4552 };
4553
4554 scoped_refptr<DelayedSocketData> data(
4555 new DelayedSocketData(
4556 1, // wait for one write to finish before reading.
4557 data_reads, arraysize(data_reads),
4558 data_writes, arraysize(data_writes)));
4559 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4560 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4561 proxy_ssl.next_proto = "spdy/2";
4562 proxy_ssl.was_npn_negotiated = true;
4563
4564 session_deps.socket_factory.AddSocketDataProvider(data.get());
4565 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4566
4567 TestCompletionCallback callback;
4568
4569 scoped_ptr<HttpTransaction> trans(
4570 new HttpNetworkTransaction(CreateSession(&session_deps)));
4571
4572 int rv = trans->Start(&request, &callback, BoundNetLog());
4573 EXPECT_EQ(ERR_IO_PENDING, rv);
4574
4575 rv = callback.WaitForResult();
4576 EXPECT_EQ(OK, rv);
4577 const HttpResponseInfo* response = trans->GetResponseInfo();
4578
4579 ASSERT_FALSE(response == NULL);
4580
4581 EXPECT_EQ(302, response->headers->response_code());
4582 std::string url;
4583 EXPECT_TRUE(response->headers->IsRedirect(&url));
4584 EXPECT_EQ("http://login.example.com/", url);
4585}
4586
4587// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4588TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4589 SessionDependencies session_deps(
4590 ProxyService::CreateFixed("https://proxy:70"));
4591
4592 HttpRequestInfo request;
4593 request.method = "GET";
4594 request.url = GURL("https://www.google.com/");
4595 request.load_flags = 0;
4596
4597 MockWrite data_writes[] = {
4598 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4599 "Host: www.google.com\r\n"
4600 "Proxy-Connection: keep-alive\r\n\r\n"),
4601 };
4602
4603 MockRead data_reads[] = {
4604 MockRead("HTTP/1.1 404 Not Found\r\n"),
4605 MockRead("Content-Length: 23\r\n\r\n"),
4606 MockRead("The host does not exist"),
4607 MockRead(false, OK),
4608 };
4609
4610 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4611 data_writes, arraysize(data_writes));
4612 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4613
4614 session_deps.socket_factory.AddSocketDataProvider(&data);
4615 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4616
4617 TestCompletionCallback callback;
4618
4619 scoped_ptr<HttpTransaction> trans(
4620 new HttpNetworkTransaction(CreateSession(&session_deps)));
4621
4622 int rv = trans->Start(&request, &callback, BoundNetLog());
4623 EXPECT_EQ(ERR_IO_PENDING, rv);
4624
4625 rv = callback.WaitForResult();
4626 EXPECT_EQ(OK, rv);
4627 const HttpResponseInfo* response = trans->GetResponseInfo();
4628
4629 ASSERT_FALSE(response == NULL);
4630
4631 EXPECT_EQ(404, response->headers->response_code());
4632 EXPECT_EQ(23, response->headers->GetContentLength());
4633 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4634 EXPECT_FALSE(response->ssl_info.is_valid());
4635
4636 std::string response_data;
4637 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4638 EXPECT_EQ("The host does not exist", response_data);
4639}
4640
4641// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4642// request
4643TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4644 SessionDependencies session_deps(
4645 ProxyService::CreateFixed("https://proxy:70"));
4646
4647 HttpRequestInfo request;
4648 request.method = "GET";
4649 request.url = GURL("https://www.google.com/");
4650 request.load_flags = 0;
4651
4652 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4653 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4654 MockWrite data_writes[] = {
4655 CreateMockWrite(*conn.get(), 0, false),
4656 };
4657
4658 static const char* const kExtraHeaders[] = {
4659 "location",
4660 "http://login.example.com/",
4661 };
4662 scoped_ptr<spdy::SpdyFrame> resp(
4663 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4664 arraysize(kExtraHeaders)/2, 1));
4665 scoped_ptr<spdy::SpdyFrame> body(
4666 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4667 MockRead data_reads[] = {
4668 CreateMockRead(*resp.get(), 1, false),
4669 CreateMockRead(*body.get(), 2, false),
4670 MockRead(true, 0, 3), // EOF
4671 };
4672
4673 scoped_refptr<DelayedSocketData> data(
4674 new DelayedSocketData(
4675 1, // wait for one write to finish before reading.
4676 data_reads, arraysize(data_reads),
4677 data_writes, arraysize(data_writes)));
4678 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4679 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4680 proxy_ssl.next_proto = "spdy/2";
4681 proxy_ssl.was_npn_negotiated = true;
4682
4683 session_deps.socket_factory.AddSocketDataProvider(data.get());
4684 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4685
4686 TestCompletionCallback callback;
4687
4688 scoped_ptr<HttpTransaction> trans(
4689 new HttpNetworkTransaction(CreateSession(&session_deps)));
4690
4691 int rv = trans->Start(&request, &callback, BoundNetLog());
4692 EXPECT_EQ(ERR_IO_PENDING, rv);
4693
4694 rv = callback.WaitForResult();
4695 EXPECT_EQ(OK, rv);
4696 const HttpResponseInfo* response = trans->GetResponseInfo();
4697
4698 ASSERT_FALSE(response == NULL);
4699
4700 EXPECT_EQ(404, response->headers->response_code());
4701 EXPECT_FALSE(response->ssl_info.is_valid());
4702
4703 std::string response_data;
4704 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4705 EXPECT_EQ("The host does not exist", response_data);
4706}
4707
[email protected]2df19bb2010-08-25 20:13:464708// Test HTTPS connections to a site with a bad certificate, going through an
4709// HTTPS proxy
4710TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004711 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464712
4713 HttpRequestInfo request;
4714 request.method = "GET";
4715 request.url = GURL("https://www.google.com/");
4716 request.load_flags = 0;
4717
4718 // Attempt to fetch the URL from a server with a bad cert
4719 MockWrite bad_cert_writes[] = {
4720 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4721 "Host: www.google.com\r\n"
4722 "Proxy-Connection: keep-alive\r\n\r\n"),
4723 };
4724
4725 MockRead bad_cert_reads[] = {
4726 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4727 MockRead(false, OK)
4728 };
4729
4730 // Attempt to fetch the URL with a good cert
4731 MockWrite good_data_writes[] = {
4732 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4733 "Host: www.google.com\r\n"
4734 "Proxy-Connection: keep-alive\r\n\r\n"),
4735 MockWrite("GET / HTTP/1.1\r\n"
4736 "Host: www.google.com\r\n"
4737 "Connection: keep-alive\r\n\r\n"),
4738 };
4739
4740 MockRead good_cert_reads[] = {
4741 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4742 MockRead("HTTP/1.0 200 OK\r\n"),
4743 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4744 MockRead("Content-Length: 100\r\n\r\n"),
4745 MockRead(false, OK),
4746 };
4747
4748 StaticSocketDataProvider ssl_bad_certificate(
4749 bad_cert_reads, arraysize(bad_cert_reads),
4750 bad_cert_writes, arraysize(bad_cert_writes));
4751 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4752 good_data_writes, arraysize(good_data_writes));
4753 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4754 SSLSocketDataProvider ssl(true, OK);
4755
4756 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4757 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4758 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4759 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4760
4761 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4762 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4763 session_deps.socket_factory.AddSocketDataProvider(&data);
4764 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4765
4766 TestCompletionCallback callback;
4767
4768 scoped_ptr<HttpTransaction> trans(
4769 new HttpNetworkTransaction(CreateSession(&session_deps)));
4770
4771 int rv = trans->Start(&request, &callback, BoundNetLog());
4772 EXPECT_EQ(ERR_IO_PENDING, rv);
4773
4774 rv = callback.WaitForResult();
4775 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4776
4777 rv = trans->RestartIgnoringLastError(&callback);
4778 EXPECT_EQ(ERR_IO_PENDING, rv);
4779
4780 rv = callback.WaitForResult();
4781 EXPECT_EQ(OK, rv);
4782
4783 const HttpResponseInfo* response = trans->GetResponseInfo();
4784
4785 EXPECT_FALSE(response == NULL);
4786 EXPECT_EQ(100, response->headers->GetContentLength());
4787}
4788
[email protected]1c773ea12009-04-28 19:58:424789TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424790 HttpRequestInfo request;
4791 request.method = "GET";
4792 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434793 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4794 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424795
[email protected]cb9bf6ca2011-01-28 13:15:274796 SessionDependencies session_deps;
4797 scoped_ptr<HttpTransaction> trans(
4798 new HttpNetworkTransaction(CreateSession(&session_deps)));
4799
[email protected]1c773ea12009-04-28 19:58:424800 MockWrite data_writes[] = {
4801 MockWrite("GET / HTTP/1.1\r\n"
4802 "Host: www.google.com\r\n"
4803 "Connection: keep-alive\r\n"
4804 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4805 };
4806
4807 // Lastly, the server responds with the actual content.
4808 MockRead data_reads[] = {
4809 MockRead("HTTP/1.0 200 OK\r\n"),
4810 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4811 MockRead("Content-Length: 100\r\n\r\n"),
4812 MockRead(false, OK),
4813 };
4814
[email protected]31a2bfe2010-02-09 08:03:394815 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4816 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594817 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424818
4819 TestCompletionCallback callback;
4820
[email protected]5a1d7ca2010-04-28 20:12:274821 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424822 EXPECT_EQ(ERR_IO_PENDING, rv);
4823
4824 rv = callback.WaitForResult();
4825 EXPECT_EQ(OK, rv);
4826}
4827
[email protected]da81f132010-08-18 23:39:294828TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:294829 HttpRequestInfo request;
4830 request.method = "GET";
4831 request.url = GURL("https://www.google.com/");
4832 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4833 "Chromium Ultra Awesome X Edition");
4834
[email protected]cb9bf6ca2011-01-28 13:15:274835 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4836 scoped_ptr<HttpTransaction> trans(
4837 new HttpNetworkTransaction(CreateSession(&session_deps)));
4838
[email protected]da81f132010-08-18 23:39:294839 MockWrite data_writes[] = {
4840 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4841 "Host: www.google.com\r\n"
4842 "Proxy-Connection: keep-alive\r\n"
4843 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4844 };
4845 MockRead data_reads[] = {
4846 // Return an error, so the transaction stops here (this test isn't
4847 // interested in the rest).
4848 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4849 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4850 MockRead("Proxy-Connection: close\r\n\r\n"),
4851 };
4852
4853 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4854 data_writes, arraysize(data_writes));
4855 session_deps.socket_factory.AddSocketDataProvider(&data);
4856
4857 TestCompletionCallback callback;
4858
4859 int rv = trans->Start(&request, &callback, BoundNetLog());
4860 EXPECT_EQ(ERR_IO_PENDING, rv);
4861
4862 rv = callback.WaitForResult();
4863 EXPECT_EQ(OK, rv);
4864}
4865
[email protected]1c773ea12009-04-28 19:58:424866TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:424867 HttpRequestInfo request;
4868 request.method = "GET";
4869 request.url = GURL("http://www.google.com/");
4870 request.load_flags = 0;
4871 request.referrer = GURL("http://the.previous.site.com/");
4872
[email protected]cb9bf6ca2011-01-28 13:15:274873 SessionDependencies session_deps;
4874 scoped_ptr<HttpTransaction> trans(
4875 new HttpNetworkTransaction(CreateSession(&session_deps)));
4876
[email protected]1c773ea12009-04-28 19:58:424877 MockWrite data_writes[] = {
4878 MockWrite("GET / HTTP/1.1\r\n"
4879 "Host: www.google.com\r\n"
4880 "Connection: keep-alive\r\n"
4881 "Referer: http://the.previous.site.com/\r\n\r\n"),
4882 };
4883
4884 // Lastly, the server responds with the actual content.
4885 MockRead data_reads[] = {
4886 MockRead("HTTP/1.0 200 OK\r\n"),
4887 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4888 MockRead("Content-Length: 100\r\n\r\n"),
4889 MockRead(false, OK),
4890 };
4891
[email protected]31a2bfe2010-02-09 08:03:394892 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4893 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594894 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424895
4896 TestCompletionCallback callback;
4897
[email protected]5a1d7ca2010-04-28 20:12:274898 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424899 EXPECT_EQ(ERR_IO_PENDING, rv);
4900
4901 rv = callback.WaitForResult();
4902 EXPECT_EQ(OK, rv);
4903}
4904
4905TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424906 HttpRequestInfo request;
4907 request.method = "POST";
4908 request.url = GURL("http://www.google.com/");
4909
[email protected]cb9bf6ca2011-01-28 13:15:274910 SessionDependencies session_deps;
4911 scoped_ptr<HttpTransaction> trans(
4912 new HttpNetworkTransaction(CreateSession(&session_deps)));
4913
[email protected]1c773ea12009-04-28 19:58:424914 MockWrite data_writes[] = {
4915 MockWrite("POST / HTTP/1.1\r\n"
4916 "Host: www.google.com\r\n"
4917 "Connection: keep-alive\r\n"
4918 "Content-Length: 0\r\n\r\n"),
4919 };
4920
4921 // Lastly, the server responds with the actual content.
4922 MockRead data_reads[] = {
4923 MockRead("HTTP/1.0 200 OK\r\n"),
4924 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4925 MockRead("Content-Length: 100\r\n\r\n"),
4926 MockRead(false, OK),
4927 };
4928
[email protected]31a2bfe2010-02-09 08:03:394929 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4930 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594931 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424932
4933 TestCompletionCallback callback;
4934
[email protected]5a1d7ca2010-04-28 20:12:274935 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424936 EXPECT_EQ(ERR_IO_PENDING, rv);
4937
4938 rv = callback.WaitForResult();
4939 EXPECT_EQ(OK, rv);
4940}
4941
4942TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424943 HttpRequestInfo request;
4944 request.method = "PUT";
4945 request.url = GURL("http://www.google.com/");
4946
[email protected]cb9bf6ca2011-01-28 13:15:274947 SessionDependencies session_deps;
4948 scoped_ptr<HttpTransaction> trans(
4949 new HttpNetworkTransaction(CreateSession(&session_deps)));
4950
[email protected]1c773ea12009-04-28 19:58:424951 MockWrite data_writes[] = {
4952 MockWrite("PUT / HTTP/1.1\r\n"
4953 "Host: www.google.com\r\n"
4954 "Connection: keep-alive\r\n"
4955 "Content-Length: 0\r\n\r\n"),
4956 };
4957
4958 // Lastly, the server responds with the actual content.
4959 MockRead data_reads[] = {
4960 MockRead("HTTP/1.0 200 OK\r\n"),
4961 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4962 MockRead("Content-Length: 100\r\n\r\n"),
4963 MockRead(false, OK),
4964 };
4965
[email protected]31a2bfe2010-02-09 08:03:394966 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4967 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594968 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424969
4970 TestCompletionCallback callback;
4971
[email protected]5a1d7ca2010-04-28 20:12:274972 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424973 EXPECT_EQ(ERR_IO_PENDING, rv);
4974
4975 rv = callback.WaitForResult();
4976 EXPECT_EQ(OK, rv);
4977}
4978
4979TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424980 HttpRequestInfo request;
4981 request.method = "HEAD";
4982 request.url = GURL("http://www.google.com/");
4983
[email protected]cb9bf6ca2011-01-28 13:15:274984 SessionDependencies session_deps;
4985 scoped_ptr<HttpTransaction> trans(
4986 new HttpNetworkTransaction(CreateSession(&session_deps)));
4987
[email protected]1c773ea12009-04-28 19:58:424988 MockWrite data_writes[] = {
4989 MockWrite("HEAD / HTTP/1.1\r\n"
4990 "Host: www.google.com\r\n"
4991 "Connection: keep-alive\r\n"
4992 "Content-Length: 0\r\n\r\n"),
4993 };
4994
4995 // Lastly, the server responds with the actual content.
4996 MockRead data_reads[] = {
4997 MockRead("HTTP/1.0 200 OK\r\n"),
4998 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4999 MockRead("Content-Length: 100\r\n\r\n"),
5000 MockRead(false, OK),
5001 };
5002
[email protected]31a2bfe2010-02-09 08:03:395003 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5004 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595005 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425006
5007 TestCompletionCallback callback;
5008
[email protected]5a1d7ca2010-04-28 20:12:275009 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425010 EXPECT_EQ(ERR_IO_PENDING, rv);
5011
5012 rv = callback.WaitForResult();
5013 EXPECT_EQ(OK, rv);
5014}
5015
5016TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425017 HttpRequestInfo request;
5018 request.method = "GET";
5019 request.url = GURL("http://www.google.com/");
5020 request.load_flags = LOAD_BYPASS_CACHE;
5021
[email protected]cb9bf6ca2011-01-28 13:15:275022 SessionDependencies session_deps;
5023 scoped_ptr<HttpTransaction> trans(
5024 new HttpNetworkTransaction(CreateSession(&session_deps)));
5025
[email protected]1c773ea12009-04-28 19:58:425026 MockWrite data_writes[] = {
5027 MockWrite("GET / HTTP/1.1\r\n"
5028 "Host: www.google.com\r\n"
5029 "Connection: keep-alive\r\n"
5030 "Pragma: no-cache\r\n"
5031 "Cache-Control: no-cache\r\n\r\n"),
5032 };
5033
5034 // Lastly, the server responds with the actual content.
5035 MockRead data_reads[] = {
5036 MockRead("HTTP/1.0 200 OK\r\n"),
5037 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5038 MockRead("Content-Length: 100\r\n\r\n"),
5039 MockRead(false, OK),
5040 };
5041
[email protected]31a2bfe2010-02-09 08:03:395042 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5043 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595044 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425045
5046 TestCompletionCallback callback;
5047
[email protected]5a1d7ca2010-04-28 20:12:275048 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425049 EXPECT_EQ(ERR_IO_PENDING, rv);
5050
5051 rv = callback.WaitForResult();
5052 EXPECT_EQ(OK, rv);
5053}
5054
5055TEST_F(HttpNetworkTransactionTest,
5056 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425057 HttpRequestInfo request;
5058 request.method = "GET";
5059 request.url = GURL("http://www.google.com/");
5060 request.load_flags = LOAD_VALIDATE_CACHE;
5061
[email protected]cb9bf6ca2011-01-28 13:15:275062 SessionDependencies session_deps;
5063 scoped_ptr<HttpTransaction> trans(
5064 new HttpNetworkTransaction(CreateSession(&session_deps)));
5065
[email protected]1c773ea12009-04-28 19:58:425066 MockWrite data_writes[] = {
5067 MockWrite("GET / HTTP/1.1\r\n"
5068 "Host: www.google.com\r\n"
5069 "Connection: keep-alive\r\n"
5070 "Cache-Control: max-age=0\r\n\r\n"),
5071 };
5072
5073 // Lastly, the server responds with the actual content.
5074 MockRead data_reads[] = {
5075 MockRead("HTTP/1.0 200 OK\r\n"),
5076 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5077 MockRead("Content-Length: 100\r\n\r\n"),
5078 MockRead(false, OK),
5079 };
5080
[email protected]31a2bfe2010-02-09 08:03:395081 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5082 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595083 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425084
5085 TestCompletionCallback callback;
5086
[email protected]5a1d7ca2010-04-28 20:12:275087 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425088 EXPECT_EQ(ERR_IO_PENDING, rv);
5089
5090 rv = callback.WaitForResult();
5091 EXPECT_EQ(OK, rv);
5092}
5093
5094TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425095 HttpRequestInfo request;
5096 request.method = "GET";
5097 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435098 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425099
[email protected]cb9bf6ca2011-01-28 13:15:275100 SessionDependencies session_deps;
5101 scoped_ptr<HttpTransaction> trans(
5102 new HttpNetworkTransaction(CreateSession(&session_deps)));
5103
[email protected]1c773ea12009-04-28 19:58:425104 MockWrite data_writes[] = {
5105 MockWrite("GET / HTTP/1.1\r\n"
5106 "Host: www.google.com\r\n"
5107 "Connection: keep-alive\r\n"
5108 "FooHeader: Bar\r\n\r\n"),
5109 };
5110
5111 // Lastly, the server responds with the actual content.
5112 MockRead data_reads[] = {
5113 MockRead("HTTP/1.0 200 OK\r\n"),
5114 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5115 MockRead("Content-Length: 100\r\n\r\n"),
5116 MockRead(false, OK),
5117 };
5118
[email protected]31a2bfe2010-02-09 08:03:395119 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5120 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595121 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425122
5123 TestCompletionCallback callback;
5124
[email protected]5a1d7ca2010-04-28 20:12:275125 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425126 EXPECT_EQ(ERR_IO_PENDING, rv);
5127
5128 rv = callback.WaitForResult();
5129 EXPECT_EQ(OK, rv);
5130}
5131
[email protected]270c6412010-03-29 22:02:475132TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475133 HttpRequestInfo request;
5134 request.method = "GET";
5135 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435136 request.extra_headers.SetHeader("referer", "www.foo.com");
5137 request.extra_headers.SetHeader("hEllo", "Kitty");
5138 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475139
[email protected]cb9bf6ca2011-01-28 13:15:275140 SessionDependencies session_deps;
5141 scoped_ptr<HttpTransaction> trans(
5142 new HttpNetworkTransaction(CreateSession(&session_deps)));
5143
[email protected]270c6412010-03-29 22:02:475144 MockWrite data_writes[] = {
5145 MockWrite("GET / HTTP/1.1\r\n"
5146 "Host: www.google.com\r\n"
5147 "Connection: keep-alive\r\n"
5148 "hEllo: Kitty\r\n"
5149 "FoO: bar\r\n\r\n"),
5150 };
5151
5152 // Lastly, the server responds with the actual content.
5153 MockRead data_reads[] = {
5154 MockRead("HTTP/1.0 200 OK\r\n"),
5155 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5156 MockRead("Content-Length: 100\r\n\r\n"),
5157 MockRead(false, OK),
5158 };
5159
5160 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5161 data_writes, arraysize(data_writes));
5162 session_deps.socket_factory.AddSocketDataProvider(&data);
5163
5164 TestCompletionCallback callback;
5165
[email protected]5a1d7ca2010-04-28 20:12:275166 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:475167 EXPECT_EQ(ERR_IO_PENDING, rv);
5168
5169 rv = callback.WaitForResult();
5170 EXPECT_EQ(OK, rv);
5171}
5172
[email protected]3cd17242009-06-23 02:59:025173TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275174 HttpRequestInfo request;
5175 request.method = "GET";
5176 request.url = GURL("http://www.google.com/");
5177 request.load_flags = 0;
5178
[email protected]80d6524d2009-08-18 03:58:095179 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005180 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025181
5182 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435183 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025184
[email protected]3cd17242009-06-23 02:59:025185 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5186 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5187
5188 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355189 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025190 MockWrite("GET / HTTP/1.1\r\n"
5191 "Host: www.google.com\r\n"
5192 "Connection: keep-alive\r\n\r\n")
5193 };
5194
5195 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595196 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025197 MockRead("HTTP/1.0 200 OK\r\n"),
5198 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5199 MockRead("Payload"),
5200 MockRead(false, OK)
5201 };
5202
[email protected]31a2bfe2010-02-09 08:03:395203 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5204 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595205 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025206
5207 TestCompletionCallback callback;
5208
[email protected]5a1d7ca2010-04-28 20:12:275209 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025210 EXPECT_EQ(ERR_IO_PENDING, rv);
5211
5212 rv = callback.WaitForResult();
5213 EXPECT_EQ(OK, rv);
5214
5215 const HttpResponseInfo* response = trans->GetResponseInfo();
5216 EXPECT_FALSE(response == NULL);
5217
5218 std::string response_text;
5219 rv = ReadTransaction(trans.get(), &response_text);
5220 EXPECT_EQ(OK, rv);
5221 EXPECT_EQ("Payload", response_text);
5222}
5223
5224TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275225 HttpRequestInfo request;
5226 request.method = "GET";
5227 request.url = GURL("https://www.google.com/");
5228 request.load_flags = 0;
5229
[email protected]80d6524d2009-08-18 03:58:095230 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005231 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025232
5233 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435234 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025235
[email protected]3cd17242009-06-23 02:59:025236 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5237 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5238
5239 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355240 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5241 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025242 MockWrite("GET / HTTP/1.1\r\n"
5243 "Host: www.google.com\r\n"
5244 "Connection: keep-alive\r\n\r\n")
5245 };
5246
5247 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355248 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5249 arraysize(read_buffer)),
5250 MockRead("HTTP/1.0 200 OK\r\n"),
5251 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5252 MockRead("Payload"),
5253 MockRead(false, OK)
5254 };
5255
[email protected]31a2bfe2010-02-09 08:03:395256 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5257 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595258 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355259
[email protected]5ecc992a42009-11-11 01:41:595260 SSLSocketDataProvider ssl(true, OK);
5261 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355262
5263 TestCompletionCallback callback;
5264
[email protected]5a1d7ca2010-04-28 20:12:275265 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355266 EXPECT_EQ(ERR_IO_PENDING, rv);
5267
5268 rv = callback.WaitForResult();
5269 EXPECT_EQ(OK, rv);
5270
5271 const HttpResponseInfo* response = trans->GetResponseInfo();
5272 EXPECT_FALSE(response == NULL);
5273
5274 std::string response_text;
5275 rv = ReadTransaction(trans.get(), &response_text);
5276 EXPECT_EQ(OK, rv);
5277 EXPECT_EQ("Payload", response_text);
5278}
5279
5280TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275281 HttpRequestInfo request;
5282 request.method = "GET";
5283 request.url = GURL("http://www.google.com/");
5284 request.load_flags = 0;
5285
[email protected]80d6524d2009-08-18 03:58:095286 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005287 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355288
5289 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435290 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355291
[email protected]e0c27be2009-07-15 13:09:355292 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5293 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375294 const char kSOCKS5OkRequest[] = {
5295 0x05, // Version
5296 0x01, // Command (CONNECT)
5297 0x00, // Reserved.
5298 0x03, // Address type (DOMAINNAME).
5299 0x0E, // Length of domain (14)
5300 // Domain string:
5301 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5302 0x00, 0x50, // 16-bit port (80)
5303 };
[email protected]e0c27be2009-07-15 13:09:355304 const char kSOCKS5OkResponse[] =
5305 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5306
5307 MockWrite data_writes[] = {
5308 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5309 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5310 MockWrite("GET / HTTP/1.1\r\n"
5311 "Host: www.google.com\r\n"
5312 "Connection: keep-alive\r\n\r\n")
5313 };
5314
5315 MockRead data_reads[] = {
5316 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5317 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5318 MockRead("HTTP/1.0 200 OK\r\n"),
5319 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5320 MockRead("Payload"),
5321 MockRead(false, OK)
5322 };
5323
[email protected]31a2bfe2010-02-09 08:03:395324 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5325 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595326 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355327
5328 TestCompletionCallback callback;
5329
[email protected]5a1d7ca2010-04-28 20:12:275330 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355331 EXPECT_EQ(ERR_IO_PENDING, rv);
5332
5333 rv = callback.WaitForResult();
5334 EXPECT_EQ(OK, rv);
5335
5336 const HttpResponseInfo* response = trans->GetResponseInfo();
5337 EXPECT_FALSE(response == NULL);
5338
5339 std::string response_text;
5340 rv = ReadTransaction(trans.get(), &response_text);
5341 EXPECT_EQ(OK, rv);
5342 EXPECT_EQ("Payload", response_text);
5343}
5344
5345TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275346 HttpRequestInfo request;
5347 request.method = "GET";
5348 request.url = GURL("https://www.google.com/");
5349 request.load_flags = 0;
5350
[email protected]80d6524d2009-08-18 03:58:095351 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005352 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355353
5354 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435355 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355356
[email protected]e0c27be2009-07-15 13:09:355357 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5358 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375359 const unsigned char kSOCKS5OkRequest[] = {
5360 0x05, // Version
5361 0x01, // Command (CONNECT)
5362 0x00, // Reserved.
5363 0x03, // Address type (DOMAINNAME).
5364 0x0E, // Length of domain (14)
5365 // Domain string:
5366 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5367 0x01, 0xBB, // 16-bit port (443)
5368 };
5369
[email protected]e0c27be2009-07-15 13:09:355370 const char kSOCKS5OkResponse[] =
5371 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5372
5373 MockWrite data_writes[] = {
5374 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5375 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5376 arraysize(kSOCKS5OkRequest)),
5377 MockWrite("GET / HTTP/1.1\r\n"
5378 "Host: www.google.com\r\n"
5379 "Connection: keep-alive\r\n\r\n")
5380 };
5381
5382 MockRead data_reads[] = {
5383 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5384 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025385 MockRead("HTTP/1.0 200 OK\r\n"),
5386 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5387 MockRead("Payload"),
5388 MockRead(false, OK)
5389 };
5390
[email protected]31a2bfe2010-02-09 08:03:395391 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5392 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595393 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025394
[email protected]5ecc992a42009-11-11 01:41:595395 SSLSocketDataProvider ssl(true, OK);
5396 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025397
5398 TestCompletionCallback callback;
5399
[email protected]5a1d7ca2010-04-28 20:12:275400 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025401 EXPECT_EQ(ERR_IO_PENDING, rv);
5402
5403 rv = callback.WaitForResult();
5404 EXPECT_EQ(OK, rv);
5405
5406 const HttpResponseInfo* response = trans->GetResponseInfo();
5407 EXPECT_FALSE(response == NULL);
5408
5409 std::string response_text;
5410 rv = ReadTransaction(trans.get(), &response_text);
5411 EXPECT_EQ(OK, rv);
5412 EXPECT_EQ("Payload", response_text);
5413}
5414
[email protected]04e5be32009-06-26 20:00:315415// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065416
5417struct GroupNameTest {
5418 std::string proxy_server;
5419 std::string url;
5420 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185421 bool ssl;
[email protected]2d731a32010-04-29 01:04:065422};
5423
5424scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
5425 const std::string& proxy_server) {
[email protected]81cdfcd2010-10-16 00:49:005426 SessionDependencies session_deps(ProxyService::CreateFixed(proxy_server));
[email protected]2d731a32010-04-29 01:04:065427 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5428
5429 HttpAlternateProtocols* alternate_protocols =
5430 session->mutable_alternate_protocols();
5431 alternate_protocols->SetAlternateProtocolFor(
5432 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:355433 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065434
5435 return session;
5436}
5437
5438int GroupNameTransactionHelper(
5439 const std::string& url,
5440 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065441 HttpRequestInfo request;
5442 request.method = "GET";
5443 request.url = GURL(url);
5444 request.load_flags = 0;
5445
[email protected]cb9bf6ca2011-01-28 13:15:275446 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5447
[email protected]2d731a32010-04-29 01:04:065448 TestCompletionCallback callback;
5449
5450 // We do not complete this request, the dtor will clean the transaction up.
5451 return trans->Start(&request, &callback, BoundNetLog());
5452}
5453
5454TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5455 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315456 {
[email protected]2d731a32010-04-29 01:04:065457 "", // unused
[email protected]04e5be32009-06-26 20:00:315458 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545459 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185460 false,
[email protected]2ff8b312010-04-26 22:20:545461 },
5462 {
[email protected]2d731a32010-04-29 01:04:065463 "", // unused
[email protected]2ff8b312010-04-26 22:20:545464 "http://[2001:1418:13:1::25]/direct",
5465 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185466 false,
[email protected]04e5be32009-06-26 20:00:315467 },
[email protected]04e5be32009-06-26 20:00:315468
5469 // SSL Tests
5470 {
[email protected]2d731a32010-04-29 01:04:065471 "", // unused
[email protected]04e5be32009-06-26 20:00:315472 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025473 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185474 true,
[email protected]04e5be32009-06-26 20:00:315475 },
5476 {
[email protected]2d731a32010-04-29 01:04:065477 "", // unused
5478 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025479 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185480 true,
[email protected]04e5be32009-06-26 20:00:315481 },
5482 {
[email protected]2d731a32010-04-29 01:04:065483 "", // unused
[email protected]2ff8b312010-04-26 22:20:545484 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025485 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185486 true,
[email protected]2ff8b312010-04-26 22:20:545487 },
[email protected]2d731a32010-04-29 01:04:065488 };
[email protected]2ff8b312010-04-26 22:20:545489
[email protected]8e6441ca2010-08-19 05:56:385490 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065491
5492 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5493 scoped_refptr<HttpNetworkSession> session(
5494 SetupSessionForGroupNameTests(tests[i].proxy_server));
5495
5496 HttpNetworkSessionPeer peer(session);
[email protected]2431756e2010-09-29 20:26:135497 CaptureGroupNameTCPSocketPool* tcp_conn_pool =
5498 new CaptureGroupNameTCPSocketPool(session);
[email protected]2d731a32010-04-29 01:04:065499 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]2431756e2010-09-29 20:26:135500 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5501 new CaptureGroupNameSSLSocketPool(session.get());
[email protected]e60e47a2010-07-14 03:37:185502 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065503
5504 EXPECT_EQ(ERR_IO_PENDING,
5505 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185506 if (tests[i].ssl)
5507 EXPECT_EQ(tests[i].expected_group_name,
5508 ssl_conn_pool->last_group_name_received());
5509 else
5510 EXPECT_EQ(tests[i].expected_group_name,
5511 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065512 }
5513
[email protected]8e6441ca2010-08-19 05:56:385514 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065515}
5516
5517TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5518 const GroupNameTest tests[] = {
5519 {
5520 "http_proxy",
5521 "http://www.google.com/http_proxy_normal",
5522 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185523 false,
[email protected]2d731a32010-04-29 01:04:065524 },
5525
5526 // SSL Tests
5527 {
5528 "http_proxy",
5529 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025530 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185531 true,
[email protected]2d731a32010-04-29 01:04:065532 },
[email protected]af3490e2010-10-16 21:02:295533
[email protected]9faeded92010-04-29 20:03:055534 {
5535 "http_proxy",
5536 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025537 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185538 true,
[email protected]9faeded92010-04-29 20:03:055539 },
[email protected]2d731a32010-04-29 01:04:065540 };
5541
[email protected]8e6441ca2010-08-19 05:56:385542 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065543
5544 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5545 scoped_refptr<HttpNetworkSession> session(
5546 SetupSessionForGroupNameTests(tests[i].proxy_server));
5547
5548 HttpNetworkSessionPeer peer(session);
5549
[email protected]e60e47a2010-07-14 03:37:185550 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135551 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
5552 new CaptureGroupNameHttpProxySocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185553 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135554 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5555 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185556 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065557
5558 EXPECT_EQ(ERR_IO_PENDING,
5559 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185560 if (tests[i].ssl)
5561 EXPECT_EQ(tests[i].expected_group_name,
5562 ssl_conn_pool->last_group_name_received());
5563 else
5564 EXPECT_EQ(tests[i].expected_group_name,
5565 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065566 }
5567
[email protected]8e6441ca2010-08-19 05:56:385568 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065569}
5570
5571TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5572 const GroupNameTest tests[] = {
5573 {
5574 "socks4://socks_proxy:1080",
5575 "http://www.google.com/socks4_direct",
5576 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185577 false,
[email protected]2d731a32010-04-29 01:04:065578 },
5579 {
5580 "socks5://socks_proxy:1080",
5581 "http://www.google.com/socks5_direct",
5582 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185583 false,
[email protected]2d731a32010-04-29 01:04:065584 },
5585
5586 // SSL Tests
5587 {
5588 "socks4://socks_proxy:1080",
5589 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025590 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185591 true,
[email protected]2d731a32010-04-29 01:04:065592 },
5593 {
5594 "socks5://socks_proxy:1080",
5595 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025596 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185597 true,
[email protected]2d731a32010-04-29 01:04:065598 },
[email protected]af3490e2010-10-16 21:02:295599
[email protected]9faeded92010-04-29 20:03:055600 {
5601 "socks4://socks_proxy:1080",
5602 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025603 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185604 true,
[email protected]9faeded92010-04-29 20:03:055605 },
[email protected]04e5be32009-06-26 20:00:315606 };
5607
[email protected]8e6441ca2010-08-19 05:56:385608 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545609
[email protected]04e5be32009-06-26 20:00:315610 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:065611 scoped_refptr<HttpNetworkSession> session(
5612 SetupSessionForGroupNameTests(tests[i].proxy_server));
5613 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315614
[email protected]e60e47a2010-07-14 03:37:185615 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135616 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
5617 new CaptureGroupNameSOCKSSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185618 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135619 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5620 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185621 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315622
[email protected]5695b8c2009-09-30 21:36:435623 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315624
[email protected]2d731a32010-04-29 01:04:065625 EXPECT_EQ(ERR_IO_PENDING,
5626 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185627 if (tests[i].ssl)
5628 EXPECT_EQ(tests[i].expected_group_name,
5629 ssl_conn_pool->last_group_name_received());
5630 else
5631 EXPECT_EQ(tests[i].expected_group_name,
5632 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315633 }
[email protected]2ff8b312010-04-26 22:20:545634
[email protected]8e6441ca2010-08-19 05:56:385635 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315636}
5637
[email protected]9172a982009-06-06 00:30:255638TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275639 HttpRequestInfo request;
5640 request.method = "GET";
5641 request.url = GURL("http://www.google.com/");
5642
[email protected]5c6a17e2009-06-10 00:54:545643 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005644 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325645
[email protected]69719062010-01-05 20:09:215646 // This simulates failure resolving all hostnames; that means we will fail
5647 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325648 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5649
[email protected]9172a982009-06-06 00:30:255650 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435651 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255652
[email protected]9172a982009-06-06 00:30:255653 TestCompletionCallback callback;
5654
[email protected]5a1d7ca2010-04-28 20:12:275655 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255656 EXPECT_EQ(ERR_IO_PENDING, rv);
5657
[email protected]9172a982009-06-06 00:30:255658 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015659 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255660}
5661
[email protected]f3e6c1e2009-06-15 20:52:125662// Host resolution observer used by
5663// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5664// resovle requests are issued with a referrer of |expected_referrer|.
5665class ResolutionReferrerObserver : public HostResolver::Observer {
5666 public:
5667 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5668 : expected_referrer_(expected_referrer),
5669 called_start_with_referrer_(false),
5670 called_finish_with_referrer_(false) {
5671 }
5672
5673 virtual void OnStartResolution(int id,
5674 const HostResolver::RequestInfo& info) {
5675 if (info.referrer() == expected_referrer_)
5676 called_start_with_referrer_ = true;
5677 }
5678
5679 virtual void OnFinishResolutionWithStatus(
5680 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5681 if (info.referrer() == expected_referrer_)
5682 called_finish_with_referrer_ = true;
5683 }
5684
[email protected]eb255d32009-06-17 02:11:035685 virtual void OnCancelResolution(int id,
5686 const HostResolver::RequestInfo& info ) {
5687 FAIL() << "Should not be cancelling any requests!";
5688 }
5689
[email protected]f3e6c1e2009-06-15 20:52:125690 bool did_complete_with_expected_referrer() const {
5691 return called_start_with_referrer_ && called_finish_with_referrer_;
5692 }
5693
5694 private:
5695 GURL expected_referrer_;
5696 bool called_start_with_referrer_;
5697 bool called_finish_with_referrer_;
5698
5699 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5700};
5701
5702// Make sure that when HostResolver::Resolve() is invoked, it passes through
5703// the "referrer". This is depended on by the DNS prefetch observer.
5704TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5705 GURL referrer = GURL("http://expected-referrer/");
5706 EXPECT_TRUE(referrer.is_valid());
5707 ResolutionReferrerObserver resolution_observer(referrer);
5708
[email protected]cb9bf6ca2011-01-28 13:15:275709 // Issue a request, containing an HTTP referrer.
5710 HttpRequestInfo request;
5711 request.method = "GET";
5712 request.referrer = referrer;
5713 request.url = GURL("http://www.google.com/");
5714
[email protected]f3e6c1e2009-06-15 20:52:125715 SessionDependencies session_deps;
5716 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435717 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125718
5719 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145720 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125721
5722 // Connect up a mock socket which will fail when reading.
5723 MockRead data_reads[] = {
5724 MockRead(false, ERR_FAILED),
5725 };
[email protected]31a2bfe2010-02-09 08:03:395726 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595727 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125728
[email protected]f3e6c1e2009-06-15 20:52:125729 // Run the request until it fails reading from the socket.
5730 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275731 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125732 EXPECT_EQ(ERR_IO_PENDING, rv);
5733 rv = callback.WaitForResult();
5734 EXPECT_EQ(ERR_FAILED, rv);
5735
5736 // Check that the host resolution observer saw |referrer|.
5737 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5738}
5739
[email protected]685af592010-05-11 19:31:245740// Base test to make sure that when the load flags for a request specify to
5741// bypass the cache, the DNS cache is not used.
5742void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275743 // Issue a request, asking to bypass the cache(s).
5744 HttpRequestInfo request;
5745 request.method = "GET";
5746 request.load_flags = load_flags;
5747 request.url = GURL("http://www.google.com/");
5748
[email protected]3b9cca42009-06-16 01:08:285749 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325750
[email protected]a2c2fb92009-07-18 07:31:045751 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545752 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325753
[email protected]3b9cca42009-06-16 01:08:285754 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435755 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285756
5757 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5758 // a synchronous lookup.)
5759 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145760 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105761 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275762 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285763 EXPECT_EQ(OK, rv);
5764
5765 // Verify that it was added to host cache, by doing a subsequent async lookup
5766 // and confirming it completes synchronously.
5767 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465768 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105769 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275770 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325771 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285772
5773 // Inject a failure the next time that "www.google.com" is resolved. This way
5774 // we can tell if the next lookup hit the cache, or the "network".
5775 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325776 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285777
5778 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5779 // first read -- this won't be reached as the host resolution will fail first.
5780 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395781 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595782 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285783
[email protected]3b9cca42009-06-16 01:08:285784 // Run the request.
5785 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275786 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285787 ASSERT_EQ(ERR_IO_PENDING, rv);
5788 rv = callback.WaitForResult();
5789
5790 // If we bypassed the cache, we would have gotten a failure while resolving
5791 // "www.google.com".
5792 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5793}
5794
[email protected]685af592010-05-11 19:31:245795// There are multiple load flags that should trigger the host cache bypass.
5796// Test each in isolation:
5797TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5798 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5799}
5800
5801TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5802 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5803}
5804
5805TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5806 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5807}
5808
[email protected]0877e3d2009-10-17 22:29:575809// Make sure we can handle an error when writing the request.
5810TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5811 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275812 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575813
5814 HttpRequestInfo request;
5815 request.method = "GET";
5816 request.url = GURL("http://www.foo.com/");
5817 request.load_flags = 0;
5818
5819 MockWrite write_failure[] = {
5820 MockWrite(true, ERR_CONNECTION_RESET),
5821 };
[email protected]31a2bfe2010-02-09 08:03:395822 StaticSocketDataProvider data(NULL, 0,
5823 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595824 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575825
5826 TestCompletionCallback callback;
5827
5828 scoped_ptr<HttpTransaction> trans(
5829 new HttpNetworkTransaction(CreateSession(&session_deps)));
5830
[email protected]5a1d7ca2010-04-28 20:12:275831 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575832 EXPECT_EQ(ERR_IO_PENDING, rv);
5833
5834 rv = callback.WaitForResult();
5835 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5836}
5837
5838// Check that a connection closed after the start of the headers finishes ok.
5839TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5840 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275841 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575842
5843 HttpRequestInfo request;
5844 request.method = "GET";
5845 request.url = GURL("http://www.foo.com/");
5846 request.load_flags = 0;
5847
5848 MockRead data_reads[] = {
5849 MockRead("HTTP/1."),
5850 MockRead(false, OK),
5851 };
5852
[email protected]31a2bfe2010-02-09 08:03:395853 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595854 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575855
5856 TestCompletionCallback callback;
5857
5858 scoped_ptr<HttpTransaction> trans(
5859 new HttpNetworkTransaction(CreateSession(&session_deps)));
5860
[email protected]5a1d7ca2010-04-28 20:12:275861 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575862 EXPECT_EQ(ERR_IO_PENDING, rv);
5863
5864 rv = callback.WaitForResult();
5865 EXPECT_EQ(OK, rv);
5866
5867 const HttpResponseInfo* response = trans->GetResponseInfo();
5868 EXPECT_TRUE(response != NULL);
5869
5870 EXPECT_TRUE(response->headers != NULL);
5871 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5872
5873 std::string response_data;
5874 rv = ReadTransaction(trans.get(), &response_data);
5875 EXPECT_EQ(OK, rv);
5876 EXPECT_EQ("", response_data);
5877}
5878
5879// Make sure that a dropped connection while draining the body for auth
5880// restart does the right thing.
5881TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5882 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275883 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575884
5885 HttpRequestInfo request;
5886 request.method = "GET";
5887 request.url = GURL("http://www.google.com/");
5888 request.load_flags = 0;
5889
5890 MockWrite data_writes1[] = {
5891 MockWrite("GET / HTTP/1.1\r\n"
5892 "Host: www.google.com\r\n"
5893 "Connection: keep-alive\r\n\r\n"),
5894 };
5895
5896 MockRead data_reads1[] = {
5897 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5898 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5899 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5900 MockRead("Content-Length: 14\r\n\r\n"),
5901 MockRead("Unauth"),
5902 MockRead(true, ERR_CONNECTION_RESET),
5903 };
5904
[email protected]31a2bfe2010-02-09 08:03:395905 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5906 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595907 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575908
5909 // After calling trans->RestartWithAuth(), this is the request we should
5910 // be issuing -- the final header line contains the credentials.
5911 MockWrite data_writes2[] = {
5912 MockWrite("GET / HTTP/1.1\r\n"
5913 "Host: www.google.com\r\n"
5914 "Connection: keep-alive\r\n"
5915 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5916 };
5917
5918 // Lastly, the server responds with the actual content.
5919 MockRead data_reads2[] = {
5920 MockRead("HTTP/1.1 200 OK\r\n"),
5921 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5922 MockRead("Content-Length: 100\r\n\r\n"),
5923 MockRead(false, OK),
5924 };
5925
[email protected]31a2bfe2010-02-09 08:03:395926 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5927 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595928 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575929
5930 TestCompletionCallback callback1;
5931
[email protected]0b0bf032010-09-21 18:08:505932 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5933
[email protected]5a1d7ca2010-04-28 20:12:275934 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575935 EXPECT_EQ(ERR_IO_PENDING, rv);
5936
5937 rv = callback1.WaitForResult();
5938 EXPECT_EQ(OK, rv);
5939
5940 const HttpResponseInfo* response = trans->GetResponseInfo();
5941 EXPECT_FALSE(response == NULL);
5942
5943 // The password prompt info should have been set in response->auth_challenge.
5944 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5945
5946 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5947 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5948 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5949
5950 TestCompletionCallback callback2;
5951
[email protected]13c8a092010-07-29 06:15:445952 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:575953 EXPECT_EQ(ERR_IO_PENDING, rv);
5954
5955 rv = callback2.WaitForResult();
5956 EXPECT_EQ(OK, rv);
5957
5958 response = trans->GetResponseInfo();
5959 EXPECT_FALSE(response == NULL);
5960 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5961 EXPECT_EQ(100, response->headers->GetContentLength());
5962}
5963
5964// Test HTTPS connections going through a proxy that sends extra data.
5965TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:005966 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:575967
5968 HttpRequestInfo request;
5969 request.method = "GET";
5970 request.url = GURL("https://www.google.com/");
5971 request.load_flags = 0;
5972
5973 MockRead proxy_reads[] = {
5974 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5975 MockRead(false, OK)
5976 };
5977
[email protected]31a2bfe2010-02-09 08:03:395978 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595979 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575980
[email protected]5ecc992a42009-11-11 01:41:595981 session_deps.socket_factory.AddSocketDataProvider(&data);
5982 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575983
5984 TestCompletionCallback callback;
5985
5986 session_deps.socket_factory.ResetNextMockIndexes();
5987
5988 scoped_ptr<HttpTransaction> trans(
5989 new HttpNetworkTransaction(CreateSession(&session_deps)));
5990
[email protected]5a1d7ca2010-04-28 20:12:275991 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575992 EXPECT_EQ(ERR_IO_PENDING, rv);
5993
5994 rv = callback.WaitForResult();
5995 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5996}
5997
[email protected]e22e1362009-11-23 21:31:125998TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:465999 HttpRequestInfo request;
6000 request.method = "GET";
6001 request.url = GURL("http://www.google.com/");
6002 request.load_flags = 0;
6003
[email protected]cb9bf6ca2011-01-28 13:15:276004 SessionDependencies session_deps;
6005 scoped_ptr<HttpTransaction> trans(
6006 new HttpNetworkTransaction(CreateSession(&session_deps)));
6007
[email protected]e22e1362009-11-23 21:31:126008 MockRead data_reads[] = {
6009 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6010 MockRead(false, OK),
6011 };
[email protected]9492e4a2010-02-24 00:58:466012
6013 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6014 session_deps.socket_factory.AddSocketDataProvider(&data);
6015
6016 TestCompletionCallback callback;
6017
[email protected]5a1d7ca2010-04-28 20:12:276018 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466019 EXPECT_EQ(ERR_IO_PENDING, rv);
6020
6021 EXPECT_EQ(OK, callback.WaitForResult());
6022
6023 const HttpResponseInfo* response = trans->GetResponseInfo();
6024 EXPECT_TRUE(response != NULL);
6025
6026 EXPECT_TRUE(response->headers != NULL);
6027 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6028
6029 std::string response_data;
6030 rv = ReadTransaction(trans.get(), &response_data);
6031 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126032}
6033
[email protected]95d88ffe2010-02-04 21:25:336034TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336035 HttpRequestInfo request;
6036 request.method = "POST";
6037 request.url = GURL("http://www.google.com/upload");
6038 request.upload_data = new UploadData;
6039 request.load_flags = 0;
6040
[email protected]cb9bf6ca2011-01-28 13:15:276041 SessionDependencies session_deps;
6042 scoped_ptr<HttpTransaction> trans(
6043 new HttpNetworkTransaction(CreateSession(&session_deps)));
6044
[email protected]95d88ffe2010-02-04 21:25:336045 FilePath temp_file_path;
6046 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6047 const uint64 kFakeSize = 100000; // file is actually blank
6048
6049 std::vector<UploadData::Element> elements;
6050 UploadData::Element element;
6051 element.SetToFilePath(temp_file_path);
6052 element.SetContentLength(kFakeSize);
6053 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536054 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:336055 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6056
6057 MockRead data_reads[] = {
6058 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6059 MockRead("hello world"),
6060 MockRead(false, OK),
6061 };
[email protected]31a2bfe2010-02-09 08:03:396062 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336063 session_deps.socket_factory.AddSocketDataProvider(&data);
6064
6065 TestCompletionCallback callback;
6066
[email protected]5a1d7ca2010-04-28 20:12:276067 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336068 EXPECT_EQ(ERR_IO_PENDING, rv);
6069
6070 rv = callback.WaitForResult();
6071 EXPECT_EQ(OK, rv);
6072
6073 const HttpResponseInfo* response = trans->GetResponseInfo();
6074 EXPECT_TRUE(response != NULL);
6075
6076 EXPECT_TRUE(response->headers != NULL);
6077 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6078
6079 std::string response_data;
6080 rv = ReadTransaction(trans.get(), &response_data);
6081 EXPECT_EQ(OK, rv);
6082 EXPECT_EQ("hello world", response_data);
6083
6084 file_util::Delete(temp_file_path, false);
6085}
6086
[email protected]6624b4622010-03-29 19:58:366087TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276088 HttpRequestInfo request;
6089 request.method = "POST";
6090 request.url = GURL("http://www.google.com/upload");
6091 request.upload_data = new UploadData;
6092 request.load_flags = 0;
6093
[email protected]6624b4622010-03-29 19:58:366094 // If we try to upload an unreadable file, the network stack should report
6095 // the file size as zero and upload zero bytes for that file.
6096 SessionDependencies session_deps;
6097 scoped_ptr<HttpTransaction> trans(
6098 new HttpNetworkTransaction(CreateSession(&session_deps)));
6099
6100 FilePath temp_file;
6101 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6102 std::string temp_file_content("Unreadable file.");
6103 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6104 temp_file_content.length()));
6105 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6106
[email protected]6624b4622010-03-29 19:58:366107 std::vector<UploadData::Element> elements;
6108 UploadData::Element element;
6109 element.SetToFilePath(temp_file);
6110 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536111 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366112
6113 MockRead data_reads[] = {
6114 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6115 MockRead(false, OK),
6116 };
6117 MockWrite data_writes[] = {
6118 MockWrite("POST /upload HTTP/1.1\r\n"
6119 "Host: www.google.com\r\n"
6120 "Connection: keep-alive\r\n"
6121 "Content-Length: 0\r\n\r\n"),
6122 MockWrite(false, OK),
6123 };
6124 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6125 arraysize(data_writes));
6126 session_deps.socket_factory.AddSocketDataProvider(&data);
6127
6128 TestCompletionCallback callback;
6129
[email protected]5a1d7ca2010-04-28 20:12:276130 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366131 EXPECT_EQ(ERR_IO_PENDING, rv);
6132
6133 rv = callback.WaitForResult();
6134 EXPECT_EQ(OK, rv);
6135
6136 const HttpResponseInfo* response = trans->GetResponseInfo();
6137 EXPECT_TRUE(response != NULL);
6138 EXPECT_TRUE(response->headers != NULL);
6139 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6140
6141 file_util::Delete(temp_file, false);
6142}
6143
6144TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276145 HttpRequestInfo request;
6146 request.method = "POST";
6147 request.url = GURL("http://www.google.com/upload");
6148 request.upload_data = new UploadData;
6149 request.load_flags = 0;
6150
[email protected]6624b4622010-03-29 19:58:366151 SessionDependencies session_deps;
6152 scoped_ptr<HttpTransaction> trans(
6153 new HttpNetworkTransaction(CreateSession(&session_deps)));
6154
6155 FilePath temp_file;
6156 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6157 std::string temp_file_contents("Unreadable file.");
6158 std::string unreadable_contents(temp_file_contents.length(), '\0');
6159 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6160 temp_file_contents.length()));
6161
[email protected]6624b4622010-03-29 19:58:366162 std::vector<UploadData::Element> elements;
6163 UploadData::Element element;
6164 element.SetToFilePath(temp_file);
6165 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536166 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366167
6168 MockRead data_reads[] = {
6169 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6170 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6171 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6172
6173 MockRead("HTTP/1.1 200 OK\r\n"),
6174 MockRead("Content-Length: 0\r\n\r\n"),
6175 MockRead(false, OK),
6176 };
6177 MockWrite data_writes[] = {
6178 MockWrite("POST /upload HTTP/1.1\r\n"
6179 "Host: www.google.com\r\n"
6180 "Connection: keep-alive\r\n"
6181 "Content-Length: 16\r\n\r\n"),
6182 MockWrite(false, temp_file_contents.c_str()),
6183
6184 MockWrite("POST /upload HTTP/1.1\r\n"
6185 "Host: www.google.com\r\n"
6186 "Connection: keep-alive\r\n"
6187 "Content-Length: 16\r\n"
6188 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6189 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6190 MockWrite(false, OK),
6191 };
6192 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6193 arraysize(data_writes));
6194 session_deps.socket_factory.AddSocketDataProvider(&data);
6195
6196 TestCompletionCallback callback1;
6197
[email protected]5a1d7ca2010-04-28 20:12:276198 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366199 EXPECT_EQ(ERR_IO_PENDING, rv);
6200
6201 rv = callback1.WaitForResult();
6202 EXPECT_EQ(OK, rv);
6203
6204 const HttpResponseInfo* response = trans->GetResponseInfo();
6205 EXPECT_TRUE(response != NULL);
6206 EXPECT_TRUE(response->headers != NULL);
6207 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
6208
6209 // The password prompt info should have been set in response->auth_challenge.
6210 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6211 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6212 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
6213 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6214
6215 // Now make the file unreadable and try again.
6216 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6217
6218 TestCompletionCallback callback2;
6219
[email protected]13c8a092010-07-29 06:15:446220 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:366221 EXPECT_EQ(ERR_IO_PENDING, rv);
6222
6223 rv = callback2.WaitForResult();
6224 EXPECT_EQ(OK, rv);
6225
6226 response = trans->GetResponseInfo();
6227 EXPECT_TRUE(response != NULL);
6228 EXPECT_TRUE(response->headers != NULL);
6229 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6230 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6231
6232 file_util::Delete(temp_file, false);
6233}
6234
[email protected]aeefc9e82010-02-19 16:18:276235// Tests that changes to Auth realms are treated like auth rejections.
6236TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6237 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276238
6239 HttpRequestInfo request;
6240 request.method = "GET";
6241 request.url = GURL("http://www.google.com/");
6242 request.load_flags = 0;
6243
6244 // First transaction will request a resource and receive a Basic challenge
6245 // with realm="first_realm".
6246 MockWrite data_writes1[] = {
6247 MockWrite("GET / HTTP/1.1\r\n"
6248 "Host: www.google.com\r\n"
6249 "Connection: keep-alive\r\n"
6250 "\r\n"),
6251 };
6252 MockRead data_reads1[] = {
6253 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6254 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6255 "\r\n"),
6256 };
6257
6258 // After calling trans->RestartWithAuth(), provide an Authentication header
6259 // for first_realm. The server will reject and provide a challenge with
6260 // second_realm.
6261 MockWrite data_writes2[] = {
6262 MockWrite("GET / HTTP/1.1\r\n"
6263 "Host: www.google.com\r\n"
6264 "Connection: keep-alive\r\n"
6265 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6266 "\r\n"),
6267 };
6268 MockRead data_reads2[] = {
6269 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6270 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6271 "\r\n"),
6272 };
6273
6274 // This again fails, and goes back to first_realm. Make sure that the
6275 // entry is removed from cache.
6276 MockWrite data_writes3[] = {
6277 MockWrite("GET / HTTP/1.1\r\n"
6278 "Host: www.google.com\r\n"
6279 "Connection: keep-alive\r\n"
6280 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6281 "\r\n"),
6282 };
6283 MockRead data_reads3[] = {
6284 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6285 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6286 "\r\n"),
6287 };
6288
6289 // Try one last time (with the correct password) and get the resource.
6290 MockWrite data_writes4[] = {
6291 MockWrite("GET / HTTP/1.1\r\n"
6292 "Host: www.google.com\r\n"
6293 "Connection: keep-alive\r\n"
6294 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6295 "\r\n"),
6296 };
6297 MockRead data_reads4[] = {
6298 MockRead("HTTP/1.1 200 OK\r\n"
6299 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506300 "Content-Length: 5\r\n"
6301 "\r\n"
6302 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276303 };
6304
6305 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6306 data_writes1, arraysize(data_writes1));
6307 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6308 data_writes2, arraysize(data_writes2));
6309 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6310 data_writes3, arraysize(data_writes3));
6311 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6312 data_writes4, arraysize(data_writes4));
6313 session_deps.socket_factory.AddSocketDataProvider(&data1);
6314 session_deps.socket_factory.AddSocketDataProvider(&data2);
6315 session_deps.socket_factory.AddSocketDataProvider(&data3);
6316 session_deps.socket_factory.AddSocketDataProvider(&data4);
6317
6318 TestCompletionCallback callback1;
6319
[email protected]0b0bf032010-09-21 18:08:506320 scoped_ptr<HttpTransaction> trans(
6321 new HttpNetworkTransaction(CreateSession(&session_deps)));
6322
[email protected]aeefc9e82010-02-19 16:18:276323 // Issue the first request with Authorize headers. There should be a
6324 // password prompt for first_realm waiting to be filled in after the
6325 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:276326 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276327 EXPECT_EQ(ERR_IO_PENDING, rv);
6328 rv = callback1.WaitForResult();
6329 EXPECT_EQ(OK, rv);
6330 const HttpResponseInfo* response = trans->GetResponseInfo();
6331 ASSERT_FALSE(response == NULL);
6332 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6333 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6334 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6335 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6336
6337 // Issue the second request with an incorrect password. There should be a
6338 // password prompt for second_realm waiting to be filled in after the
6339 // transaction completes.
6340 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:446341 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:276342 EXPECT_EQ(ERR_IO_PENDING, rv);
6343 rv = callback2.WaitForResult();
6344 EXPECT_EQ(OK, rv);
6345 response = trans->GetResponseInfo();
6346 ASSERT_FALSE(response == NULL);
6347 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6348 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6349 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
6350 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6351
6352 // Issue the third request with another incorrect password. There should be
6353 // a password prompt for first_realm waiting to be filled in. If the password
6354 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6355 // first_realm was not correctly removed.
6356 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:446357 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:276358 EXPECT_EQ(ERR_IO_PENDING, rv);
6359 rv = callback3.WaitForResult();
6360 EXPECT_EQ(OK, rv);
6361 response = trans->GetResponseInfo();
6362 ASSERT_FALSE(response == NULL);
6363 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6364 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6365 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6366 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6367
6368 // Issue the fourth request with the correct password and username.
6369 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:446370 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:276371 EXPECT_EQ(ERR_IO_PENDING, rv);
6372 rv = callback4.WaitForResult();
6373 EXPECT_EQ(OK, rv);
6374 response = trans->GetResponseInfo();
6375 ASSERT_FALSE(response == NULL);
6376 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6377}
6378
[email protected]564b4912010-03-09 16:30:426379TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:386380 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
6381 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426382
[email protected]564b4912010-03-09 16:30:426383 SessionDependencies session_deps;
6384
6385 MockRead data_reads[] = {
6386 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356387 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426388 MockRead("hello world"),
6389 MockRead(false, OK),
6390 };
6391
6392 HttpRequestInfo request;
6393 request.method = "GET";
6394 request.url = GURL("http://www.google.com/");
6395 request.load_flags = 0;
6396
6397 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6398
6399 session_deps.socket_factory.AddSocketDataProvider(&data);
6400
6401 TestCompletionCallback callback;
6402
6403 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6404 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6405
[email protected]5a1d7ca2010-04-28 20:12:276406 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426407 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536408
[email protected]2fbaecf22010-07-22 22:20:356409 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426410 const HttpAlternateProtocols& alternate_protocols =
6411 session->alternate_protocols();
6412 EXPECT_FALSE(
6413 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6414
6415 EXPECT_EQ(OK, callback.WaitForResult());
6416
6417 const HttpResponseInfo* response = trans->GetResponseInfo();
6418 ASSERT_TRUE(response != NULL);
6419 ASSERT_TRUE(response->headers != NULL);
6420 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536421 EXPECT_FALSE(response->was_fetched_via_spdy);
6422 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576423 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:426424
6425 std::string response_data;
6426 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6427 EXPECT_EQ("hello world", response_data);
6428
6429 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6430 const HttpAlternateProtocols::PortProtocolPair alternate =
6431 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
6432 HttpAlternateProtocols::PortProtocolPair expected_alternate;
6433 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:356434 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426435 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426436
[email protected]8e6441ca2010-08-19 05:56:386437 HttpStreamFactory::set_use_alternate_protocols(false);
6438 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:426439}
6440
6441TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:386442 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426443 SessionDependencies session_deps;
6444
6445 HttpRequestInfo request;
6446 request.method = "GET";
6447 request.url = GURL("http://www.google.com/");
6448 request.load_flags = 0;
6449
6450 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6451 StaticSocketDataProvider first_data;
6452 first_data.set_connect_data(mock_connect);
6453 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6454
6455 MockRead data_reads[] = {
6456 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6457 MockRead("hello world"),
6458 MockRead(true, OK),
6459 };
6460 StaticSocketDataProvider second_data(
6461 data_reads, arraysize(data_reads), NULL, 0);
6462 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6463
6464 // TODO(willchan): Delete this extra data provider. It's necessary due to a
6465 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
6466 // http://crbug.com/37454.
6467 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6468
6469 TestCompletionCallback callback;
6470
6471 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6472
[email protected]2fbaecf22010-07-22 22:20:356473 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426474 HttpAlternateProtocols* alternate_protocols =
6475 session->mutable_alternate_protocols();
6476 alternate_protocols->SetAlternateProtocolFor(
6477 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:356478 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426479
6480 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6481
[email protected]5a1d7ca2010-04-28 20:12:276482 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426483 EXPECT_EQ(ERR_IO_PENDING, rv);
6484 EXPECT_EQ(OK, callback.WaitForResult());
6485
6486 const HttpResponseInfo* response = trans->GetResponseInfo();
6487 ASSERT_TRUE(response != NULL);
6488 ASSERT_TRUE(response->headers != NULL);
6489 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6490
6491 std::string response_data;
6492 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6493 EXPECT_EQ("hello world", response_data);
6494
6495 ASSERT_TRUE(
6496 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6497 const HttpAlternateProtocols::PortProtocolPair alternate =
6498 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6499 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386500 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426501}
6502
6503// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
6504// says that it does SPDY, but it just does the TLS handshake, but the NPN
6505// response does not indicate SPDY, so we just do standard HTTPS over the port.
6506// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
6507// on the original port.
[email protected]a2cb8122010-03-10 17:22:426508// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
6509// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:536510//
[email protected]a2cb8122010-03-10 17:22:426511// HttpRequestInfo request;
6512// request.method = "GET";
6513// request.url = GURL("http://www.google.com/");
6514// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:536515//
[email protected]a2cb8122010-03-10 17:22:426516// MockRead data_reads[] = {
6517// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6518// MockRead("hello world"),
6519// MockRead(true, OK),
6520// };
6521// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6522// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:536523//
[email protected]a2cb8122010-03-10 17:22:426524// SSLSocketDataProvider ssl(true, OK);
6525// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:536526//
[email protected]a2cb8122010-03-10 17:22:426527// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:536528//
[email protected]a2cb8122010-03-10 17:22:426529// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:536530//
[email protected]a2cb8122010-03-10 17:22:426531// HostPortPair http_host_port_pair;
6532// http_host_port_pair.host = "www.google.com";
6533// http_host_port_pair.port = 80;
6534// HttpAlternateProtocols* alternate_protocols =
6535// session->mutable_alternate_protocols();
6536// alternate_protocols->SetAlternateProtocolFor(
6537// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:066538// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:536539//
[email protected]a2cb8122010-03-10 17:22:426540// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:536541//
[email protected]5a1d7ca2010-04-28 20:12:276542// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:426543// EXPECT_EQ(ERR_IO_PENDING, rv);
6544// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:536545//
[email protected]a2cb8122010-03-10 17:22:426546// const HttpResponseInfo* response = trans->GetResponseInfo();
6547// ASSERT_TRUE(response != NULL);
6548// ASSERT_TRUE(response->headers != NULL);
6549// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:536550//
[email protected]a2cb8122010-03-10 17:22:426551// std::string response_data;
6552// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6553// EXPECT_EQ("hello world", response_data);
6554// }
6555
6556TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386557 HttpStreamFactory::set_use_alternate_protocols(true);
6558 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:426559 SessionDependencies session_deps;
6560
6561 HttpRequestInfo request;
6562 request.method = "GET";
6563 request.url = GURL("http://www.google.com/");
6564 request.load_flags = 0;
6565
[email protected]a2cb8122010-03-10 17:22:426566 StaticSocketDataProvider first_tcp_connect;
6567 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
6568
6569 SSLSocketDataProvider ssl(true, OK);
6570 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6571
[email protected]564b4912010-03-09 16:30:426572 MockRead data_reads[] = {
6573 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6574 MockRead("hello world"),
6575 MockRead(true, OK),
6576 };
[email protected]a2cb8122010-03-10 17:22:426577 StaticSocketDataProvider fallback_data(
6578 data_reads, arraysize(data_reads), NULL, 0);
6579 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:426580
6581 TestCompletionCallback callback;
6582
6583 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6584
[email protected]2fbaecf22010-07-22 22:20:356585 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426586 HttpAlternateProtocols* alternate_protocols =
6587 session->mutable_alternate_protocols();
6588 alternate_protocols->SetAlternateProtocolFor(
6589 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:356590 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426591
6592 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6593
[email protected]5a1d7ca2010-04-28 20:12:276594 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426595 EXPECT_EQ(ERR_IO_PENDING, rv);
6596 EXPECT_EQ(OK, callback.WaitForResult());
6597
6598 const HttpResponseInfo* response = trans->GetResponseInfo();
6599 ASSERT_TRUE(response != NULL);
6600 ASSERT_TRUE(response->headers != NULL);
6601 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6602
6603 std::string response_data;
6604 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6605 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:386606 HttpStreamFactory::set_next_protos("");
6607 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546608}
6609
6610TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386611 HttpStreamFactory::set_use_alternate_protocols(true);
6612 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546613 SessionDependencies session_deps;
6614
6615 HttpRequestInfo request;
6616 request.method = "GET";
6617 request.url = GURL("http://www.google.com/");
6618 request.load_flags = 0;
6619
6620 MockRead data_reads[] = {
6621 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356622 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546623 MockRead("hello world"),
6624 MockRead(true, OK),
6625 };
6626
6627 StaticSocketDataProvider first_transaction(
6628 data_reads, arraysize(data_reads), NULL, 0);
6629 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6630
6631 SSLSocketDataProvider ssl(true, OK);
6632 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356633 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536634 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546635 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6636
[email protected]2bd93022010-07-17 00:58:446637 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136638 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546639
[email protected]2bd93022010-07-17 00:58:446640 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6641 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546642 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136643 CreateMockRead(*resp),
6644 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546645 MockRead(true, 0, 0),
6646 };
6647
6648 scoped_refptr<DelayedSocketData> spdy_data(
6649 new DelayedSocketData(
6650 1, // wait for one write to finish before reading.
6651 spdy_reads, arraysize(spdy_reads),
6652 spdy_writes, arraysize(spdy_writes)));
6653 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6654
6655 TestCompletionCallback callback;
6656
6657 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6658 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6659
[email protected]5a1d7ca2010-04-28 20:12:276660 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546661 EXPECT_EQ(ERR_IO_PENDING, rv);
6662 EXPECT_EQ(OK, callback.WaitForResult());
6663
6664 const HttpResponseInfo* response = trans->GetResponseInfo();
6665 ASSERT_TRUE(response != NULL);
6666 ASSERT_TRUE(response->headers != NULL);
6667 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6668
6669 std::string response_data;
6670 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6671 EXPECT_EQ("hello world", response_data);
6672
6673 trans.reset(new HttpNetworkTransaction(session));
6674
[email protected]5a1d7ca2010-04-28 20:12:276675 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546676 EXPECT_EQ(ERR_IO_PENDING, rv);
6677 EXPECT_EQ(OK, callback.WaitForResult());
6678
6679 response = trans->GetResponseInfo();
6680 ASSERT_TRUE(response != NULL);
6681 ASSERT_TRUE(response->headers != NULL);
6682 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536683 EXPECT_TRUE(response->was_fetched_via_spdy);
6684 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576685 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546686
6687 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6688 EXPECT_EQ("hello!", response_data);
6689
[email protected]8e6441ca2010-08-19 05:56:386690 HttpStreamFactory::set_next_protos("");
6691 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546692}
6693
[email protected]631f1322010-04-30 17:59:116694class CapturingProxyResolver : public ProxyResolver {
6695 public:
6696 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6697 virtual ~CapturingProxyResolver() {}
6698
6699 virtual int GetProxyForURL(const GURL& url,
6700 ProxyInfo* results,
6701 CompletionCallback* callback,
6702 RequestHandle* request,
6703 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406704 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6705 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426706 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116707 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426708 return OK;
[email protected]631f1322010-04-30 17:59:116709 }
6710
6711 virtual void CancelRequest(RequestHandle request) {
6712 NOTREACHED();
6713 }
6714
[email protected]1e605472010-12-16 21:41:406715 virtual void CancelSetPacScript() {
6716 NOTREACHED();
6717 }
6718
[email protected]24476402010-07-20 20:55:176719 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116720 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426721 return OK;
[email protected]631f1322010-04-30 17:59:116722 }
6723
[email protected]24476402010-07-20 20:55:176724 const std::vector<GURL>& resolved() const { return resolved_; }
6725
6726 private:
[email protected]631f1322010-04-30 17:59:116727 std::vector<GURL> resolved_;
6728
6729 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6730};
6731
[email protected]631f1322010-04-30 17:59:116732TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386733 HttpStreamFactory::set_use_alternate_protocols(true);
6734 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116735
6736 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426737 proxy_config.set_auto_detect(true);
6738 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116739
[email protected]631f1322010-04-30 17:59:116740 CapturingProxyResolver* capturing_proxy_resolver =
6741 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386742 SessionDependencies session_deps(new ProxyService(
6743 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6744 NULL));
[email protected]631f1322010-04-30 17:59:116745
6746 HttpRequestInfo request;
6747 request.method = "GET";
6748 request.url = GURL("http://www.google.com/");
6749 request.load_flags = 0;
6750
6751 MockRead data_reads[] = {
6752 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356753 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116754 MockRead("hello world"),
6755 MockRead(true, OK),
6756 };
6757
6758 StaticSocketDataProvider first_transaction(
6759 data_reads, arraysize(data_reads), NULL, 0);
6760 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6761
6762 SSLSocketDataProvider ssl(true, OK);
6763 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356764 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536765 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116766 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6767
[email protected]2bd93022010-07-17 00:58:446768 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116769 MockWrite spdy_writes[] = {
6770 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6771 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426772 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136773 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116774 };
6775
[email protected]d911f1b2010-05-05 22:39:426776 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6777
[email protected]2bd93022010-07-17 00:58:446778 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6779 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116780 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426781 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136782 CreateMockRead(*resp.get(), 4), // 2, 4
6783 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426784 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116785 };
6786
[email protected]d911f1b2010-05-05 22:39:426787 scoped_refptr<OrderedSocketData> spdy_data(
6788 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116789 spdy_reads, arraysize(spdy_reads),
6790 spdy_writes, arraysize(spdy_writes)));
6791 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6792
6793 TestCompletionCallback callback;
6794
6795 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6796 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6797
6798 int rv = trans->Start(&request, &callback, BoundNetLog());
6799 EXPECT_EQ(ERR_IO_PENDING, rv);
6800 EXPECT_EQ(OK, callback.WaitForResult());
6801
6802 const HttpResponseInfo* response = trans->GetResponseInfo();
6803 ASSERT_TRUE(response != NULL);
6804 ASSERT_TRUE(response->headers != NULL);
6805 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536806 EXPECT_FALSE(response->was_fetched_via_spdy);
6807 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116808
6809 std::string response_data;
6810 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6811 EXPECT_EQ("hello world", response_data);
6812
6813 trans.reset(new HttpNetworkTransaction(session));
6814
6815 rv = trans->Start(&request, &callback, BoundNetLog());
6816 EXPECT_EQ(ERR_IO_PENDING, rv);
6817 EXPECT_EQ(OK, callback.WaitForResult());
6818
6819 response = trans->GetResponseInfo();
6820 ASSERT_TRUE(response != NULL);
6821 ASSERT_TRUE(response->headers != NULL);
6822 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536823 EXPECT_TRUE(response->was_fetched_via_spdy);
6824 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116825
6826 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6827 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:426828 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
6829 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116830 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426831 EXPECT_EQ("https://www.google.com/",
6832 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116833
[email protected]8e6441ca2010-08-19 05:56:386834 HttpStreamFactory::set_next_protos("");
6835 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116836}
[email protected]631f1322010-04-30 17:59:116837
[email protected]2ff8b312010-04-26 22:20:546838TEST_F(HttpNetworkTransactionTest,
6839 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386840 HttpStreamFactory::set_use_alternate_protocols(true);
6841 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546842 SessionDependencies session_deps;
6843
6844 HttpRequestInfo request;
6845 request.method = "GET";
6846 request.url = GURL("http://www.google.com/");
6847 request.load_flags = 0;
6848
6849 MockRead data_reads[] = {
6850 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356851 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546852 MockRead("hello world"),
6853 MockRead(true, OK),
6854 };
6855
6856 StaticSocketDataProvider first_transaction(
6857 data_reads, arraysize(data_reads), NULL, 0);
6858 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6859
6860 SSLSocketDataProvider ssl(true, OK);
6861 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356862 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536863 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546864 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:536865 // Make sure we use ssl for spdy here.
6866 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:546867
[email protected]2bd93022010-07-17 00:58:446868 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136869 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546870
[email protected]2bd93022010-07-17 00:58:446871 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6872 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546873 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136874 CreateMockRead(*resp),
6875 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546876 MockRead(true, 0, 0),
6877 };
6878
6879 scoped_refptr<DelayedSocketData> spdy_data(
6880 new DelayedSocketData(
6881 1, // wait for one write to finish before reading.
6882 spdy_reads, arraysize(spdy_reads),
6883 spdy_writes, arraysize(spdy_writes)));
6884 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6885
6886 TestCompletionCallback callback;
6887
6888 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6889
6890 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6891
[email protected]5a1d7ca2010-04-28 20:12:276892 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546893 EXPECT_EQ(ERR_IO_PENDING, rv);
6894 EXPECT_EQ(OK, callback.WaitForResult());
6895
6896 const HttpResponseInfo* response = trans->GetResponseInfo();
6897 ASSERT_TRUE(response != NULL);
6898 ASSERT_TRUE(response->headers != NULL);
6899 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6900
6901 std::string response_data;
6902 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6903 EXPECT_EQ("hello world", response_data);
6904
6905 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:386906 HostPortPair host_port_pair("www.google.com", 443);
6907 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:546908 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:276909 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
6910 BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:276911 scoped_refptr<TCPSocketParams> tcp_params(
6912 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:386913
6914 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
6915 EXPECT_EQ(ERR_IO_PENDING,
6916 connection->Init(host_port_pair.ToString(),tcp_params, LOWEST,
6917 &callback, session->tcp_socket_pool(),
6918 BoundNetLog()));
6919 EXPECT_EQ(OK, callback.WaitForResult());
6920
6921 SSLConfig ssl_config;
6922 session->ssl_config_service()->GetSSLConfig(&ssl_config);
6923 ClientSocket* socket = connection->release_socket();
[email protected]7ab5bbd12010-10-19 13:33:216924 socket = session->socket_factory()->CreateSSLClientSocket(
[email protected]822581d2010-12-16 17:27:156925 socket, HostPortPair("" , 443), ssl_config, NULL /* ssl_host_info */,
6926 session->cert_verifier());
[email protected]02b0c342010-09-25 21:09:386927 connection->set_socket(socket);
6928 EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
6929 EXPECT_EQ(OK, callback.WaitForResult());
6930
6931 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(connection.release(),
6932 true, OK));
6933
[email protected]2ff8b312010-04-26 22:20:546934 trans.reset(new HttpNetworkTransaction(session));
6935
[email protected]5a1d7ca2010-04-28 20:12:276936 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546937 EXPECT_EQ(ERR_IO_PENDING, rv);
6938 EXPECT_EQ(OK, callback.WaitForResult());
6939
6940 response = trans->GetResponseInfo();
6941 ASSERT_TRUE(response != NULL);
6942 ASSERT_TRUE(response->headers != NULL);
6943 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536944 EXPECT_TRUE(response->was_fetched_via_spdy);
6945 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576946 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546947
6948 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6949 EXPECT_EQ("hello!", response_data);
6950
[email protected]8e6441ca2010-08-19 05:56:386951 HttpStreamFactory::set_next_protos("");
6952 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426953}
6954
[email protected]044de0642010-06-17 10:42:156955// GenerateAuthToken is a mighty big test.
6956// It tests all permutation of GenerateAuthToken behavior:
6957// - Synchronous and Asynchronous completion.
6958// - OK or error on completion.
6959// - Direct connection, non-authenticating proxy, and authenticating proxy.
6960// - HTTP or HTTPS backend (to include proxy tunneling).
6961// - Non-authenticating and authenticating backend.
6962//
6963// In all, there are 44 reasonable permuations (for example, if there are
6964// problems generating an auth token for an authenticating proxy, we don't
6965// need to test all permutations of the backend server).
6966//
6967// The test proceeds by going over each of the configuration cases, and
6968// potentially running up to three rounds in each of the tests. The TestConfig
6969// specifies both the configuration for the test as well as the expectations
6970// for the results.
6971TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:506972 static const char kServer[] = "http://www.example.com";
6973 static const char kSecureServer[] = "https://www.example.com";
6974 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:156975 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
6976
6977 enum AuthTiming {
6978 AUTH_NONE,
6979 AUTH_SYNC,
6980 AUTH_ASYNC,
6981 };
6982
6983 const MockWrite kGet(
6984 "GET / HTTP/1.1\r\n"
6985 "Host: www.example.com\r\n"
6986 "Connection: keep-alive\r\n\r\n");
6987 const MockWrite kGetProxy(
6988 "GET http://www.example.com/ HTTP/1.1\r\n"
6989 "Host: www.example.com\r\n"
6990 "Proxy-Connection: keep-alive\r\n\r\n");
6991 const MockWrite kGetAuth(
6992 "GET / HTTP/1.1\r\n"
6993 "Host: www.example.com\r\n"
6994 "Connection: keep-alive\r\n"
6995 "Authorization: auth_token\r\n\r\n");
6996 const MockWrite kGetProxyAuth(
6997 "GET http://www.example.com/ HTTP/1.1\r\n"
6998 "Host: www.example.com\r\n"
6999 "Proxy-Connection: keep-alive\r\n"
7000 "Proxy-Authorization: auth_token\r\n\r\n");
7001 const MockWrite kGetAuthThroughProxy(
7002 "GET http://www.example.com/ HTTP/1.1\r\n"
7003 "Host: www.example.com\r\n"
7004 "Proxy-Connection: keep-alive\r\n"
7005 "Authorization: auth_token\r\n\r\n");
7006 const MockWrite kGetAuthWithProxyAuth(
7007 "GET http://www.example.com/ HTTP/1.1\r\n"
7008 "Host: www.example.com\r\n"
7009 "Proxy-Connection: keep-alive\r\n"
7010 "Proxy-Authorization: auth_token\r\n"
7011 "Authorization: auth_token\r\n\r\n");
7012 const MockWrite kConnect(
7013 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7014 "Host: www.example.com\r\n"
7015 "Proxy-Connection: keep-alive\r\n\r\n");
7016 const MockWrite kConnectProxyAuth(
7017 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7018 "Host: www.example.com\r\n"
7019 "Proxy-Connection: keep-alive\r\n"
7020 "Proxy-Authorization: auth_token\r\n\r\n");
7021
7022 const MockRead kSuccess(
7023 "HTTP/1.1 200 OK\r\n"
7024 "Content-Type: text/html; charset=iso-8859-1\r\n"
7025 "Content-Length: 3\r\n\r\n"
7026 "Yes");
7027 const MockRead kFailure(
7028 "Should not be called.");
7029 const MockRead kServerChallenge(
7030 "HTTP/1.1 401 Unauthorized\r\n"
7031 "WWW-Authenticate: Mock realm=server\r\n"
7032 "Content-Type: text/html; charset=iso-8859-1\r\n"
7033 "Content-Length: 14\r\n\r\n"
7034 "Unauthorized\r\n");
7035 const MockRead kProxyChallenge(
7036 "HTTP/1.1 407 Unauthorized\r\n"
7037 "Proxy-Authenticate: Mock realm=proxy\r\n"
7038 "Proxy-Connection: close\r\n"
7039 "Content-Type: text/html; charset=iso-8859-1\r\n"
7040 "Content-Length: 14\r\n\r\n"
7041 "Unauthorized\r\n");
7042 const MockRead kProxyConnected(
7043 "HTTP/1.1 200 Connection Established\r\n\r\n");
7044
7045 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7046 // no constructors, but the C++ compiler on Windows warns about
7047 // unspecified data in compound literals. So, moved to using constructors,
7048 // and TestRound's created with the default constructor should not be used.
7049 struct TestRound {
7050 TestRound()
7051 : expected_rv(ERR_UNEXPECTED),
7052 extra_write(NULL),
7053 extra_read(NULL) {
7054 }
7055 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7056 int expected_rv_arg)
7057 : write(write_arg),
7058 read(read_arg),
7059 expected_rv(expected_rv_arg),
7060 extra_write(NULL),
7061 extra_read(NULL) {
7062 }
7063 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7064 int expected_rv_arg, const MockWrite* extra_write_arg,
7065 const MockWrite* extra_read_arg)
7066 : write(write_arg),
7067 read(read_arg),
7068 expected_rv(expected_rv_arg),
7069 extra_write(extra_write_arg),
7070 extra_read(extra_read_arg) {
7071 }
7072 MockWrite write;
7073 MockRead read;
7074 int expected_rv;
7075 const MockWrite* extra_write;
7076 const MockRead* extra_read;
7077 };
7078
7079 static const int kNoSSL = 500;
7080
7081 struct TestConfig {
7082 const char* proxy_url;
7083 AuthTiming proxy_auth_timing;
7084 int proxy_auth_rv;
7085 const char* server_url;
7086 AuthTiming server_auth_timing;
7087 int server_auth_rv;
7088 int num_auth_rounds;
7089 int first_ssl_round;
7090 TestRound rounds[3];
7091 } test_configs[] = {
7092 // Non-authenticating HTTP server with a direct connection.
7093 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7094 { TestRound(kGet, kSuccess, OK)}},
7095 // Authenticating HTTP server with a direct connection.
7096 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7097 { TestRound(kGet, kServerChallenge, OK),
7098 TestRound(kGetAuth, kSuccess, OK)}},
7099 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7100 { TestRound(kGet, kServerChallenge, OK),
7101 TestRound(kGetAuth, kFailure, kAuthErr)}},
7102 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7103 { TestRound(kGet, kServerChallenge, OK),
7104 TestRound(kGetAuth, kSuccess, OK)}},
7105 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7106 { TestRound(kGet, kServerChallenge, OK),
7107 TestRound(kGetAuth, kFailure, kAuthErr)}},
7108 // Non-authenticating HTTP server through a non-authenticating proxy.
7109 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7110 { TestRound(kGetProxy, kSuccess, OK)}},
7111 // Authenticating HTTP server through a non-authenticating proxy.
7112 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7113 { TestRound(kGetProxy, kServerChallenge, OK),
7114 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7115 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7116 { TestRound(kGetProxy, kServerChallenge, OK),
7117 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7118 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7119 { TestRound(kGetProxy, kServerChallenge, OK),
7120 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7121 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7122 { TestRound(kGetProxy, kServerChallenge, OK),
7123 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7124 // Non-authenticating HTTP server through an authenticating proxy.
7125 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7126 { TestRound(kGetProxy, kProxyChallenge, OK),
7127 TestRound(kGetProxyAuth, kSuccess, OK)}},
7128 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7129 { TestRound(kGetProxy, kProxyChallenge, OK),
7130 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7131 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7132 { TestRound(kGetProxy, kProxyChallenge, OK),
7133 TestRound(kGetProxyAuth, kSuccess, OK)}},
7134 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7135 { TestRound(kGetProxy, kProxyChallenge, OK),
7136 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7137 // Authenticating HTTP server through an authenticating proxy.
7138 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7139 { TestRound(kGetProxy, kProxyChallenge, OK),
7140 TestRound(kGetProxyAuth, kServerChallenge, OK),
7141 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7142 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7143 { TestRound(kGetProxy, kProxyChallenge, OK),
7144 TestRound(kGetProxyAuth, kServerChallenge, OK),
7145 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7146 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7147 { TestRound(kGetProxy, kProxyChallenge, OK),
7148 TestRound(kGetProxyAuth, kServerChallenge, OK),
7149 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7150 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7151 { TestRound(kGetProxy, kProxyChallenge, OK),
7152 TestRound(kGetProxyAuth, kServerChallenge, OK),
7153 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7154 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7155 { TestRound(kGetProxy, kProxyChallenge, OK),
7156 TestRound(kGetProxyAuth, kServerChallenge, OK),
7157 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7158 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7159 { TestRound(kGetProxy, kProxyChallenge, OK),
7160 TestRound(kGetProxyAuth, kServerChallenge, OK),
7161 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7162 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7163 { TestRound(kGetProxy, kProxyChallenge, OK),
7164 TestRound(kGetProxyAuth, kServerChallenge, OK),
7165 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7166 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7167 { TestRound(kGetProxy, kProxyChallenge, OK),
7168 TestRound(kGetProxyAuth, kServerChallenge, OK),
7169 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7170 // Non-authenticating HTTPS server with a direct connection.
7171 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7172 { TestRound(kGet, kSuccess, OK)}},
7173 // Authenticating HTTPS server with a direct connection.
7174 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7175 { TestRound(kGet, kServerChallenge, OK),
7176 TestRound(kGetAuth, kSuccess, OK)}},
7177 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7178 { TestRound(kGet, kServerChallenge, OK),
7179 TestRound(kGetAuth, kFailure, kAuthErr)}},
7180 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7181 { TestRound(kGet, kServerChallenge, OK),
7182 TestRound(kGetAuth, kSuccess, OK)}},
7183 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7184 { TestRound(kGet, kServerChallenge, OK),
7185 TestRound(kGetAuth, kFailure, kAuthErr)}},
7186 // Non-authenticating HTTPS server with a non-authenticating proxy.
7187 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7188 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7189 // Authenticating HTTPS server through a non-authenticating proxy.
7190 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7191 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7192 TestRound(kGetAuth, kSuccess, OK)}},
7193 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7194 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7195 TestRound(kGetAuth, kFailure, kAuthErr)}},
7196 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7197 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7198 TestRound(kGetAuth, kSuccess, OK)}},
7199 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7200 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7201 TestRound(kGetAuth, kFailure, kAuthErr)}},
7202 // Non-Authenticating HTTPS server through an authenticating proxy.
7203 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7204 { TestRound(kConnect, kProxyChallenge, OK),
7205 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7206 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7207 { TestRound(kConnect, kProxyChallenge, OK),
7208 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7209 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7210 { TestRound(kConnect, kProxyChallenge, OK),
7211 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7212 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7213 { TestRound(kConnect, kProxyChallenge, OK),
7214 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7215 // Authenticating HTTPS server through an authenticating proxy.
7216 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7217 { TestRound(kConnect, kProxyChallenge, OK),
7218 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7219 &kGet, &kServerChallenge),
7220 TestRound(kGetAuth, kSuccess, OK)}},
7221 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7222 { TestRound(kConnect, kProxyChallenge, OK),
7223 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7224 &kGet, &kServerChallenge),
7225 TestRound(kGetAuth, kFailure, kAuthErr)}},
7226 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7227 { TestRound(kConnect, kProxyChallenge, OK),
7228 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7229 &kGet, &kServerChallenge),
7230 TestRound(kGetAuth, kSuccess, OK)}},
7231 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7232 { TestRound(kConnect, kProxyChallenge, OK),
7233 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7234 &kGet, &kServerChallenge),
7235 TestRound(kGetAuth, kFailure, kAuthErr)}},
7236 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7237 { TestRound(kConnect, kProxyChallenge, OK),
7238 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7239 &kGet, &kServerChallenge),
7240 TestRound(kGetAuth, kSuccess, OK)}},
7241 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7242 { TestRound(kConnect, kProxyChallenge, OK),
7243 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7244 &kGet, &kServerChallenge),
7245 TestRound(kGetAuth, kFailure, kAuthErr)}},
7246 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7247 { TestRound(kConnect, kProxyChallenge, OK),
7248 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7249 &kGet, &kServerChallenge),
7250 TestRound(kGetAuth, kSuccess, OK)}},
7251 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7252 { TestRound(kConnect, kProxyChallenge, OK),
7253 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7254 &kGet, &kServerChallenge),
7255 TestRound(kGetAuth, kFailure, kAuthErr)}},
7256 };
7257
7258 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:007259 HttpAuthHandlerMock::Factory* auth_factory(
7260 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:157261 session_deps.http_auth_handler_factory.reset(auth_factory);
7262
7263 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
7264 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267265
7266 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157267 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007268 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157269 std::string auth_challenge = "Mock realm=proxy";
7270 GURL origin(test_config.proxy_url);
7271 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7272 auth_challenge.end());
7273 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7274 origin, BoundNetLog());
7275 auth_handler->SetGenerateExpectation(
7276 test_config.proxy_auth_timing == AUTH_ASYNC,
7277 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:157278 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7279 }
7280 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007281 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157282 std::string auth_challenge = "Mock realm=server";
7283 GURL origin(test_config.server_url);
7284 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7285 auth_challenge.end());
7286 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7287 origin, BoundNetLog());
7288 auth_handler->SetGenerateExpectation(
7289 test_config.server_auth_timing == AUTH_ASYNC,
7290 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:157291 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7292 }
7293 if (test_config.proxy_url) {
7294 session_deps.proxy_service =
[email protected]81cdfcd2010-10-16 00:49:007295 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:157296 } else {
[email protected]ebeefff32010-09-15 05:10:027297 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:157298 }
7299
7300 HttpRequestInfo request;
7301 request.method = "GET";
7302 request.url = GURL(test_config.server_url);
7303 request.load_flags = 0;
7304
[email protected]0b0bf032010-09-21 18:08:507305 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7306 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157307
7308 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7309 const TestRound& read_write_round = test_config.rounds[round];
7310
7311 // Set up expected reads and writes.
7312 MockRead reads[2];
7313 reads[0] = read_write_round.read;
7314 size_t length_reads = 1;
7315 if (read_write_round.extra_read) {
7316 reads[1] = *read_write_round.extra_read;
7317 length_reads = 2;
7318 }
7319
7320 MockWrite writes[2];
7321 writes[0] = read_write_round.write;
7322 size_t length_writes = 1;
7323 if (read_write_round.extra_write) {
7324 writes[1] = *read_write_round.extra_write;
7325 length_writes = 2;
7326 }
7327 StaticSocketDataProvider data_provider(
7328 reads, length_reads, writes, length_writes);
7329 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7330
7331 // Add an SSL sequence if necessary.
7332 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7333 if (round >= test_config.first_ssl_round)
7334 session_deps.socket_factory.AddSSLSocketDataProvider(
7335 &ssl_socket_data_provider);
7336
7337 // Start or restart the transaction.
7338 TestCompletionCallback callback;
7339 int rv;
7340 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:507341 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:157342 } else {
[email protected]0b0bf032010-09-21 18:08:507343 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:157344 }
7345 if (rv == ERR_IO_PENDING)
7346 rv = callback.WaitForResult();
7347
7348 // Compare results with expected data.
7349 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507350 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157351 if (read_write_round.expected_rv == OK) {
7352 EXPECT_FALSE(response == NULL);
7353 } else {
7354 EXPECT_TRUE(response == NULL);
7355 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7356 continue;
7357 }
7358 if (round + 1 < test_config.num_auth_rounds) {
7359 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7360 } else {
7361 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7362 }
7363 }
[email protected]e5ae96a2010-04-14 20:12:457364 }
7365}
7366
[email protected]c871bce92010-07-15 21:51:147367TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7368 // Do multi-round authentication and make sure it works correctly.
7369 SessionDependencies session_deps;
7370 HttpAuthHandlerMock::Factory* auth_factory(
7371 new HttpAuthHandlerMock::Factory());
7372 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]ebeefff32010-09-15 05:10:027373 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]c871bce92010-07-15 21:51:147374 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7375 session_deps.host_resolver->set_synchronous_mode(true);
7376
7377 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7378 auth_handler->set_connection_based(true);
7379 std::string auth_challenge = "Mock realm=server";
7380 GURL origin("http://www.example.com");
7381 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7382 auth_challenge.end());
7383 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7384 origin, BoundNetLog());
7385 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7386
[email protected]c871bce92010-07-15 21:51:147387 int rv = OK;
7388 const HttpResponseInfo* response = NULL;
7389 HttpRequestInfo request;
7390 request.method = "GET";
7391 request.url = origin;
7392 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277393
7394 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7395 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c871bce92010-07-15 21:51:147396 TestCompletionCallback callback;
7397
7398 const MockWrite kGet(
7399 "GET / HTTP/1.1\r\n"
7400 "Host: www.example.com\r\n"
7401 "Connection: keep-alive\r\n\r\n");
7402 const MockWrite kGetAuth(
7403 "GET / HTTP/1.1\r\n"
7404 "Host: www.example.com\r\n"
7405 "Connection: keep-alive\r\n"
7406 "Authorization: auth_token\r\n\r\n");
7407
7408 const MockRead kServerChallenge(
7409 "HTTP/1.1 401 Unauthorized\r\n"
7410 "WWW-Authenticate: Mock realm=server\r\n"
7411 "Content-Type: text/html; charset=iso-8859-1\r\n"
7412 "Content-Length: 14\r\n\r\n"
7413 "Unauthorized\r\n");
7414 const MockRead kSuccess(
7415 "HTTP/1.1 200 OK\r\n"
7416 "Content-Type: text/html; charset=iso-8859-1\r\n"
7417 "Content-Length: 3\r\n\r\n"
7418 "Yes");
7419
7420 MockWrite writes[] = {
7421 // First round
7422 kGet,
7423 // Second round
7424 kGetAuth,
7425 // Third round
7426 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307427 // Fourth round
7428 kGetAuth
[email protected]c871bce92010-07-15 21:51:147429 };
7430 MockRead reads[] = {
7431 // First round
7432 kServerChallenge,
7433 // Second round
7434 kServerChallenge,
7435 // Third round
[email protected]eca50e122010-09-11 14:03:307436 kServerChallenge,
7437 // Fourth round
[email protected]c871bce92010-07-15 21:51:147438 kSuccess,
7439 };
7440 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7441 writes, arraysize(writes));
7442 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7443
7444 // First round
7445 auth_handler->SetGenerateExpectation(false, OK);
7446 rv = trans->Start(&request, &callback, BoundNetLog());
7447 if (rv == ERR_IO_PENDING)
7448 rv = callback.WaitForResult();
7449 EXPECT_EQ(OK, rv);
7450 response = trans->GetResponseInfo();
7451 ASSERT_FALSE(response == NULL);
7452 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7453
7454 // Second round
7455 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447456 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:147457 if (rv == ERR_IO_PENDING)
7458 rv = callback.WaitForResult();
7459 EXPECT_EQ(OK, rv);
7460 response = trans->GetResponseInfo();
7461 ASSERT_FALSE(response == NULL);
7462 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7463
7464 // Third round
7465 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447466 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:147467 if (rv == ERR_IO_PENDING)
7468 rv = callback.WaitForResult();
7469 EXPECT_EQ(OK, rv);
7470 response = trans->GetResponseInfo();
7471 ASSERT_FALSE(response == NULL);
7472 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]eca50e122010-09-11 14:03:307473
7474 // Fourth round
7475 auth_handler->SetGenerateExpectation(false, OK);
7476 rv = trans->RestartWithAuth(string16(), string16(), &callback);
7477 if (rv == ERR_IO_PENDING)
7478 rv = callback.WaitForResult();
7479 EXPECT_EQ(OK, rv);
7480 response = trans->GetResponseInfo();
7481 ASSERT_FALSE(response == NULL);
7482 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]c871bce92010-07-15 21:51:147483}
7484
[email protected]aeaca1f2010-04-20 22:05:217485class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7486 public:
[email protected]06650c52010-06-03 00:49:177487 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217488 : fail_all_(fail_all) {
7489 }
7490
7491 virtual MockRead GetNextRead() {
7492 if (fail_all_)
7493 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7494
7495 return MockRead(false /* async */,
7496 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7497 }
7498
7499 virtual MockWriteResult OnWrite(const std::string& data) {
7500 return MockWriteResult(false /* async */, data.size());
7501 }
7502
7503 void Reset() {
7504 }
7505
7506 private:
7507 const bool fail_all_;
7508};
7509
7510// Test that we restart a connection when we see a decompression failure from
7511// the peer during the handshake. (In the real world we'll restart with SSLv3
7512// and we won't offer DEFLATE in that case.)
7513TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7514 HttpRequestInfo request;
7515 request.method = "GET";
7516 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7517 request.load_flags = 0;
7518
7519 SessionDependencies session_deps;
7520 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7521 false /* fail all reads */);
7522 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7523 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117524 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217525 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7526 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7527 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7528 session_deps.socket_factory.AddSSLSocketDataProvider(
7529 &ssl_socket_data_provider1);
7530 session_deps.socket_factory.AddSSLSocketDataProvider(
7531 &ssl_socket_data_provider2);
7532
[email protected]e60e47a2010-07-14 03:37:187533 // Work around http://crbug.com/37454
7534 StaticSocketDataProvider bug37454_connection;
7535 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7536 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7537
[email protected]aeaca1f2010-04-20 22:05:217538 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7539 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7540 TestCompletionCallback callback;
7541
[email protected]5a1d7ca2010-04-28 20:12:277542 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217543 EXPECT_EQ(ERR_IO_PENDING, rv);
7544 EXPECT_EQ(OK, callback.WaitForResult());
7545
7546 const HttpResponseInfo* response = trans->GetResponseInfo();
7547 ASSERT_TRUE(response != NULL);
7548 ASSERT_TRUE(response->headers != NULL);
7549 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7550
7551 std::string response_data;
7552 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7553 EXPECT_EQ("ok.", response_data);
7554}
7555
7556// Test that we restart a connection if we get a decompression failure from the
7557// peer while reading the first bytes from the connection. This occurs when the
7558// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7559// in the handshake.
7560TEST_F(HttpNetworkTransactionTest,
7561 RestartAfterTLSDecompressionFailureWithFalseStart) {
7562 HttpRequestInfo request;
7563 request.method = "GET";
7564 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7565 request.load_flags = 0;
7566
7567 SessionDependencies session_deps;
7568 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7569 true /* fail all reads */);
7570 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7571 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7572 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7573 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7574 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7575 session_deps.socket_factory.AddSSLSocketDataProvider(
7576 &ssl_socket_data_provider1);
7577 session_deps.socket_factory.AddSSLSocketDataProvider(
7578 &ssl_socket_data_provider2);
7579
7580 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7581 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7582 TestCompletionCallback callback;
7583
[email protected]5a1d7ca2010-04-28 20:12:277584 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217585 EXPECT_EQ(ERR_IO_PENDING, rv);
7586 EXPECT_EQ(OK, callback.WaitForResult());
7587
7588 const HttpResponseInfo* response = trans->GetResponseInfo();
7589 ASSERT_TRUE(response != NULL);
7590 ASSERT_TRUE(response->headers != NULL);
7591 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7592
7593 std::string response_data;
7594 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7595 EXPECT_EQ("ok.", response_data);
7596}
7597
[email protected]65041fa2010-05-21 06:56:537598// This tests the case that a request is issued via http instead of spdy after
7599// npn is negotiated.
7600TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387601 HttpStreamFactory::set_use_alternate_protocols(true);
7602 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537603 SessionDependencies session_deps;
7604 HttpRequestInfo request;
7605 request.method = "GET";
7606 request.url = GURL("https://www.google.com/");
7607 request.load_flags = 0;
7608
7609 MockWrite data_writes[] = {
7610 MockWrite("GET / HTTP/1.1\r\n"
7611 "Host: www.google.com\r\n"
7612 "Connection: keep-alive\r\n\r\n"),
7613 };
7614
7615 MockRead data_reads[] = {
7616 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357617 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537618 MockRead("hello world"),
7619 MockRead(false, OK),
7620 };
7621
7622 SSLSocketDataProvider ssl(true, OK);
7623 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7624 ssl.next_proto = "http/1.1";
7625
7626 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7627
7628 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7629 data_writes, arraysize(data_writes));
7630 session_deps.socket_factory.AddSocketDataProvider(&data);
7631
7632 TestCompletionCallback callback;
7633
7634 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7635 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7636
7637 int rv = trans->Start(&request, &callback, BoundNetLog());
7638
7639 EXPECT_EQ(ERR_IO_PENDING, rv);
7640 EXPECT_EQ(OK, callback.WaitForResult());
7641
7642 const HttpResponseInfo* response = trans->GetResponseInfo();
7643 ASSERT_TRUE(response != NULL);
7644 ASSERT_TRUE(response->headers != NULL);
7645 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7646
7647 std::string response_data;
7648 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7649 EXPECT_EQ("hello world", response_data);
7650
7651 EXPECT_FALSE(response->was_fetched_via_spdy);
7652 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:577653 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:537654
[email protected]8e6441ca2010-08-19 05:56:387655 HttpStreamFactory::set_next_protos("");
7656 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537657}
[email protected]26ef6582010-06-24 02:30:477658
7659TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7660 // Simulate the SSL handshake completing with an NPN negotiation
7661 // followed by an immediate server closing of the socket.
7662 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387663 HttpStreamFactory::set_use_alternate_protocols(true);
7664 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477665 SessionDependencies session_deps;
7666
7667 HttpRequestInfo request;
7668 request.method = "GET";
7669 request.url = GURL("https://www.google.com/");
7670 request.load_flags = 0;
7671
7672 SSLSocketDataProvider ssl(true, OK);
7673 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357674 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477675 ssl.was_npn_negotiated = true;
7676 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7677
[email protected]2bd93022010-07-17 00:58:447678 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137679 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477680
7681 MockRead spdy_reads[] = {
7682 MockRead(false, 0, 0) // Not async - return 0 immediately.
7683 };
7684
7685 scoped_refptr<DelayedSocketData> spdy_data(
7686 new DelayedSocketData(
7687 0, // don't wait in this case, immediate hangup.
7688 spdy_reads, arraysize(spdy_reads),
7689 spdy_writes, arraysize(spdy_writes)));
7690 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7691
7692 TestCompletionCallback callback;
7693
7694 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7695 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7696
7697 int rv = trans->Start(&request, &callback, BoundNetLog());
7698 EXPECT_EQ(ERR_IO_PENDING, rv);
7699 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7700
[email protected]8e6441ca2010-08-19 05:56:387701 HttpStreamFactory::set_next_protos("");
7702 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477703}
[email protected]65d34382010-07-01 18:12:267704
[email protected]f45c1ee2010-08-03 00:54:307705TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7706 // This test ensures that the URL passed into the proxy is upgraded
7707 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387708 HttpStreamFactory::set_use_alternate_protocols(true);
7709 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307710 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7711
[email protected]81cdfcd2010-10-16 00:49:007712 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307713 HttpAuthHandlerMock::Factory* auth_factory =
7714 new HttpAuthHandlerMock::Factory();
7715 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7716 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7717 auth_factory->set_do_init_from_challenge(true);
7718 session_deps.http_auth_handler_factory.reset(auth_factory);
7719
7720 HttpRequestInfo request;
7721 request.method = "GET";
7722 request.url = GURL("http://www.google.com");
7723 request.load_flags = 0;
7724
7725 // First round goes unauthenticated through the proxy.
7726 MockWrite data_writes_1[] = {
7727 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7728 "Host: www.google.com\r\n"
7729 "Proxy-Connection: keep-alive\r\n"
7730 "\r\n"),
7731 };
7732 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597733 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307734 MockRead("HTTP/1.1 200 OK\r\n"
7735 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7736 "Proxy-Connection: close\r\n"
7737 "\r\n"),
7738 };
7739 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7740 data_writes_1, arraysize(data_writes_1));
7741
7742 // Second round tries to tunnel to www.google.com due to the
7743 // Alternate-Protocol announcement in the first round. It fails due
7744 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597745 // After the failure, a tunnel is established to www.google.com using
7746 // Proxy-Authorization headers. There is then a SPDY request round.
7747 //
7748 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7749 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7750 // does a Disconnect and Connect on the same socket, rather than trying
7751 // to obtain a new one.
7752 //
7753 // NOTE: Originally, the proxy response to the second CONNECT request
7754 // simply returned another 407 so the unit test could skip the SSL connection
7755 // establishment and SPDY framing issues. Alas, the
7756 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307757 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597758
[email protected]f45c1ee2010-08-03 00:54:307759 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7760 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7761 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7762
[email protected]394816e92010-08-03 07:38:597763 MockWrite data_writes_2[] = {
7764 // First connection attempt without Proxy-Authorization.
7765 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7766 "Host: www.google.com\r\n"
7767 "Proxy-Connection: keep-alive\r\n"
7768 "\r\n"),
7769
7770 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307771 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7772 "Host: www.google.com\r\n"
7773 "Proxy-Connection: keep-alive\r\n"
7774 "Proxy-Authorization: auth_token\r\n"
7775 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307776
[email protected]394816e92010-08-03 07:38:597777 // SPDY request
7778 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307779 };
[email protected]394816e92010-08-03 07:38:597780 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7781 "Proxy-Authenticate: Mock\r\n"
7782 "Proxy-Connection: close\r\n"
7783 "\r\n");
7784 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7785 MockRead data_reads_2[] = {
7786 // First connection attempt fails
7787 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7788 MockRead(true, kRejectConnectResponse,
7789 arraysize(kRejectConnectResponse) - 1, 1),
7790
7791 // Second connection attempt passes
7792 MockRead(true, kAcceptConnectResponse,
7793 arraysize(kAcceptConnectResponse) -1, 4),
7794
7795 // SPDY response
7796 CreateMockRead(*resp.get(), 6),
7797 CreateMockRead(*data.get(), 6),
7798 MockRead(true, 0, 0, 6),
7799 };
7800 scoped_refptr<OrderedSocketData> data_2(
7801 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
7802 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:307803
7804 SSLSocketDataProvider ssl(true, OK);
7805 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7806 ssl.next_proto = "spdy/2";
7807 ssl.was_npn_negotiated = true;
7808
7809 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:597810 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:307811 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7812 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7813
7814 // First round should work and provide the Alternate-Protocol state.
7815 TestCompletionCallback callback_1;
7816 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
7817 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
7818 EXPECT_EQ(ERR_IO_PENDING, rv);
7819 EXPECT_EQ(OK, callback_1.WaitForResult());
7820
7821 // Second round should attempt a tunnel connect and get an auth challenge.
7822 TestCompletionCallback callback_2;
7823 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
7824 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
7825 EXPECT_EQ(ERR_IO_PENDING, rv);
7826 EXPECT_EQ(OK, callback_2.WaitForResult());
7827 const HttpResponseInfo* response = trans_2->GetResponseInfo();
7828 ASSERT_FALSE(response == NULL);
7829 ASSERT_FALSE(response->auth_challenge.get() == NULL);
7830
7831 // Restart with auth. Tunnel should work and response received.
7832 TestCompletionCallback callback_3;
7833 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
7834 EXPECT_EQ(ERR_IO_PENDING, rv);
7835 EXPECT_EQ(OK, callback_3.WaitForResult());
7836
7837 // After all that work, these two lines (or actually, just the scheme) are
7838 // what this test is all about. Make sure it happens correctly.
7839 const GURL& request_url = auth_handler->request_url();
7840 EXPECT_EQ("https", request_url.scheme());
7841 EXPECT_EQ("www.google.com", request_url.host());
7842
[email protected]8e6441ca2010-08-19 05:56:387843 HttpStreamFactory::set_next_protos("");
7844 HttpStreamFactory::set_use_alternate_protocols(false);
7845}
7846
7847// Test that if we cancel the transaction as the connection is completing, that
7848// everything tears down correctly.
7849TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
7850 // Setup everything about the connection to complete synchronously, so that
7851 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
7852 // for is the callback from the HttpStreamRequest.
7853 // Then cancel the transaction.
7854 // Verify that we don't crash.
7855 MockConnect mock_connect(false, OK);
7856 MockRead data_reads[] = {
7857 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
7858 MockRead(false, "hello world"),
7859 MockRead(false, OK),
7860 };
7861
[email protected]8e6441ca2010-08-19 05:56:387862 HttpRequestInfo request;
7863 request.method = "GET";
7864 request.url = GURL("http://www.google.com/");
7865 request.load_flags = 0;
7866
[email protected]cb9bf6ca2011-01-28 13:15:277867 SessionDependencies session_deps;
7868 session_deps.host_resolver->set_synchronous_mode(true);
7869 scoped_ptr<HttpTransaction> trans(
7870 new HttpNetworkTransaction(CreateSession(&session_deps)));
7871
[email protected]8e6441ca2010-08-19 05:56:387872 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7873 data.set_connect_data(mock_connect);
7874 session_deps.socket_factory.AddSocketDataProvider(&data);
7875
7876 TestCompletionCallback callback;
7877
7878 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7879 int rv = trans->Start(&request, &callback, log.bound());
7880 EXPECT_EQ(ERR_IO_PENDING, rv);
7881 trans.reset(); // Cancel the transaction here.
7882
7883 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:307884}
7885
[email protected]76a505b2010-08-25 06:23:007886// Test a basic GET request through a proxy.
7887TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:007888 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007889 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7890 session_deps.net_log = log.bound().net_log();
7891 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7892
[email protected]76a505b2010-08-25 06:23:007893 HttpRequestInfo request;
7894 request.method = "GET";
7895 request.url = GURL("http://www.google.com/");
7896
7897 MockWrite data_writes1[] = {
7898 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7899 "Host: www.google.com\r\n"
7900 "Proxy-Connection: keep-alive\r\n\r\n"),
7901 };
7902
7903 MockRead data_reads1[] = {
7904 MockRead("HTTP/1.1 200 OK\r\n"),
7905 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7906 MockRead("Content-Length: 100\r\n\r\n"),
7907 MockRead(false, OK),
7908 };
7909
7910 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7911 data_writes1, arraysize(data_writes1));
7912 session_deps.socket_factory.AddSocketDataProvider(&data1);
7913
7914 TestCompletionCallback callback1;
7915
[email protected]0b0bf032010-09-21 18:08:507916 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7917
[email protected]76a505b2010-08-25 06:23:007918 int rv = trans->Start(&request, &callback1, log.bound());
7919 EXPECT_EQ(ERR_IO_PENDING, rv);
7920
7921 rv = callback1.WaitForResult();
7922 EXPECT_EQ(OK, rv);
7923
7924 const HttpResponseInfo* response = trans->GetResponseInfo();
7925 ASSERT_FALSE(response == NULL);
7926
7927 EXPECT_TRUE(response->headers->IsKeepAlive());
7928 EXPECT_EQ(200, response->headers->response_code());
7929 EXPECT_EQ(100, response->headers->GetContentLength());
7930 EXPECT_TRUE(response->was_fetched_via_proxy);
7931 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7932}
7933
7934// Test a basic HTTPS GET request through a proxy.
7935TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:007936 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007937 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7938 session_deps.net_log = log.bound().net_log();
7939 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7940
[email protected]76a505b2010-08-25 06:23:007941 HttpRequestInfo request;
7942 request.method = "GET";
7943 request.url = GURL("https://www.google.com/");
7944
7945 // Since we have proxy, should try to establish tunnel.
7946 MockWrite data_writes1[] = {
7947 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7948 "Host: www.google.com\r\n"
7949 "Proxy-Connection: keep-alive\r\n\r\n"),
7950
7951 MockWrite("GET / HTTP/1.1\r\n"
7952 "Host: www.google.com\r\n"
7953 "Connection: keep-alive\r\n\r\n"),
7954 };
7955
7956 MockRead data_reads1[] = {
7957 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7958
7959 MockRead("HTTP/1.1 200 OK\r\n"),
7960 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7961 MockRead("Content-Length: 100\r\n\r\n"),
7962 MockRead(false, OK),
7963 };
7964
7965 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7966 data_writes1, arraysize(data_writes1));
7967 session_deps.socket_factory.AddSocketDataProvider(&data1);
7968 SSLSocketDataProvider ssl(true, OK);
7969 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7970
7971 TestCompletionCallback callback1;
7972
[email protected]0b0bf032010-09-21 18:08:507973 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7974
[email protected]76a505b2010-08-25 06:23:007975 int rv = trans->Start(&request, &callback1, log.bound());
7976 EXPECT_EQ(ERR_IO_PENDING, rv);
7977
7978 rv = callback1.WaitForResult();
7979 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:407980 net::CapturingNetLog::EntryList entries;
7981 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:007982 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:407983 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:007984 NetLog::PHASE_NONE);
7985 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:407986 entries, pos,
[email protected]76a505b2010-08-25 06:23:007987 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7988 NetLog::PHASE_NONE);
7989
7990 const HttpResponseInfo* response = trans->GetResponseInfo();
7991 ASSERT_FALSE(response == NULL);
7992
7993 EXPECT_TRUE(response->headers->IsKeepAlive());
7994 EXPECT_EQ(200, response->headers->response_code());
7995 EXPECT_EQ(100, response->headers->GetContentLength());
7996 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7997 EXPECT_TRUE(response->was_fetched_via_proxy);
7998}
7999
8000// Test a basic HTTPS GET request through a proxy, but the server hangs up
8001// while establishing the tunnel.
8002TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008003 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008004 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8005 session_deps.net_log = log.bound().net_log();
8006 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8007
[email protected]76a505b2010-08-25 06:23:008008 HttpRequestInfo request;
8009 request.method = "GET";
8010 request.url = GURL("https://www.google.com/");
8011
8012 // Since we have proxy, should try to establish tunnel.
8013 MockWrite data_writes1[] = {
8014 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8015 "Host: www.google.com\r\n"
8016 "Proxy-Connection: keep-alive\r\n\r\n"),
8017
8018 MockWrite("GET / HTTP/1.1\r\n"
8019 "Host: www.google.com\r\n"
8020 "Connection: keep-alive\r\n\r\n"),
8021 };
8022
8023 MockRead data_reads1[] = {
8024 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8025 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8026 MockRead(true, 0, 0), // EOF
8027 };
8028
8029 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8030 data_writes1, arraysize(data_writes1));
8031 session_deps.socket_factory.AddSocketDataProvider(&data1);
8032 SSLSocketDataProvider ssl(true, OK);
8033 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8034
8035 TestCompletionCallback callback1;
8036
[email protected]0b0bf032010-09-21 18:08:508037 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8038
[email protected]76a505b2010-08-25 06:23:008039 int rv = trans->Start(&request, &callback1, log.bound());
8040 EXPECT_EQ(ERR_IO_PENDING, rv);
8041
8042 rv = callback1.WaitForResult();
8043 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408044 net::CapturingNetLog::EntryList entries;
8045 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008046 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408047 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008048 NetLog::PHASE_NONE);
8049 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408050 entries, pos,
[email protected]76a505b2010-08-25 06:23:008051 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8052 NetLog::PHASE_NONE);
8053}
8054
[email protected]749eefa82010-09-13 22:14:038055// Test for crbug.com/55424.
8056TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8057 SessionDependencies session_deps;
8058
8059 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8060 "https://www.google.com", false, 1, LOWEST));
8061 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8062
8063 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8064 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8065 MockRead spdy_reads[] = {
8066 CreateMockRead(*resp),
8067 CreateMockRead(*data),
8068 MockRead(true, 0, 0),
8069 };
8070
8071 scoped_refptr<DelayedSocketData> spdy_data(
8072 new DelayedSocketData(
8073 1, // wait for one write to finish before reading.
8074 spdy_reads, arraysize(spdy_reads),
8075 spdy_writes, arraysize(spdy_writes)));
8076 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8077
8078 SSLSocketDataProvider ssl(true, OK);
8079 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8080 ssl.next_proto = "spdy/2";
8081 ssl.was_npn_negotiated = true;
8082 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8083
8084 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8085
8086 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388087 HostPortPair host_port_pair("www.google.com", 443);
8088 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038089 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:278090 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
8091 BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:278092 scoped_refptr<TCPSocketParams> tcp_params(
8093 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:388094 TestCompletionCallback callback;
8095
8096 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8097 EXPECT_EQ(ERR_IO_PENDING,
8098 connection->Init(host_port_pair.ToString(), tcp_params, LOWEST,
8099 &callback, session->tcp_socket_pool(),
8100 BoundNetLog()));
8101 EXPECT_EQ(OK, callback.WaitForResult());
8102 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038103
8104 HttpRequestInfo request;
8105 request.method = "GET";
8106 request.url = GURL("https://www.google.com/");
8107 request.load_flags = 0;
8108
8109 // This is the important line that marks this as a preconnect.
8110 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8111
8112 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8113
[email protected]749eefa82010-09-13 22:14:038114 int rv = trans->Start(&request, &callback, BoundNetLog());
8115 EXPECT_EQ(ERR_IO_PENDING, rv);
8116 EXPECT_EQ(OK, callback.WaitForResult());
8117}
8118
[email protected]73b8dd222010-11-11 19:55:248119// Given a net error, cause that error to be returned from the first Write()
8120// call and verify that the HttpTransaction fails with that error.
8121static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278122 net::HttpRequestInfo request_info;
8123 request_info.url = GURL("https://www.example.com/");
8124 request_info.method = "GET";
8125 request_info.load_flags = net::LOAD_NORMAL;
8126
[email protected]73b8dd222010-11-11 19:55:248127 SessionDependencies session_deps;
8128
8129 SSLSocketDataProvider ssl_data(async, OK);
8130 net::MockWrite data_writes[] = {
8131 net::MockWrite(async, error),
8132 };
8133 net::StaticSocketDataProvider data(NULL, 0,
8134 data_writes, arraysize(data_writes));
8135 session_deps.socket_factory.AddSocketDataProvider(&data);
8136 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8137
8138 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8139 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8140
[email protected]73b8dd222010-11-11 19:55:248141 TestCompletionCallback callback;
8142 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8143 if (rv == net::ERR_IO_PENDING)
8144 rv = callback.WaitForResult();
8145 ASSERT_EQ(error, rv);
8146}
8147
8148TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8149 // Just check a grab bag of cert errors.
8150 static const int kErrors[] = {
8151 ERR_CERT_COMMON_NAME_INVALID,
8152 ERR_CERT_AUTHORITY_INVALID,
8153 ERR_CERT_DATE_INVALID,
8154 };
8155 for (size_t i = 0; i < arraysize(kErrors); i++) {
8156 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8157 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8158 }
8159}
8160
8161// Test that the transaction is restarted in the event of an NPN misprediction.
8162TEST_F(HttpNetworkTransactionTest, NPNMispredict) {
[email protected]cb9bf6ca2011-01-28 13:15:278163 net::HttpRequestInfo request_info;
8164 request_info.url = GURL("https://www.example.com/");
8165 request_info.method = "GET";
8166 request_info.load_flags = net::LOAD_NORMAL;
8167
[email protected]73b8dd222010-11-11 19:55:248168 SessionDependencies session_deps;
8169
8170 SSLSocketDataProvider ssl_data1(true /* async */, OK);
8171 SSLSocketDataProvider ssl_data2(true /* async */, OK);
8172
8173 net::MockWrite data1_writes[] = {
8174 net::MockWrite(true /* async */, ERR_SSL_SNAP_START_NPN_MISPREDICTION),
8175 };
8176 net::MockRead data2_reads[] = {
8177 net::MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8178 net::MockRead("hello world"),
8179 net::MockRead(false, net::OK),
8180 };
8181 net::MockWrite data2_writes[] = {
8182 net::MockWrite("GET / HTTP/1.1\r\n"
8183 "Host: www.example.com\r\n"
8184 "Connection: keep-alive\r\n\r\n"),
8185 };
8186 net::StaticSocketDataProvider data1(
8187 NULL, 0, data1_writes, arraysize(data1_writes));
8188 net::StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads),
8189 data2_writes, arraysize(data2_writes));
8190
8191 session_deps.socket_factory.AddSocketDataProvider(&data1);
8192 session_deps.socket_factory.AddSocketDataProvider(&data2);
8193 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8194 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8195
8196 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8197 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8198
[email protected]73b8dd222010-11-11 19:55:248199 TestCompletionCallback callback;
8200 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8201 if (rv == net::ERR_IO_PENDING)
8202 rv = callback.WaitForResult();
8203 ASSERT_EQ(OK, rv);
8204
8205 std::string contents;
8206 rv = ReadTransaction(trans.get(), &contents);
8207 EXPECT_EQ(net::OK, rv);
8208 EXPECT_EQ("hello world", contents);
8209}
8210
[email protected]bd0b6772011-01-11 19:59:308211// Ensure that a client certificate is removed from the SSL client auth
8212// cache when:
8213// 1) No proxy is involved.
8214// 2) TLS False Start is disabled.
8215// 3) The initial TLS handshake requests a client certificate.
8216// 4) The client supplies an invalid/unacceptable certificate.
8217TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278218 net::HttpRequestInfo request_info;
8219 request_info.url = GURL("https://www.example.com/");
8220 request_info.method = "GET";
8221 request_info.load_flags = net::LOAD_NORMAL;
8222
[email protected]bd0b6772011-01-11 19:59:308223 SessionDependencies session_deps;
8224
8225 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8226 cert_request->host_and_port = "www.example.com:443";
8227
8228 // [ssl_]data1 contains the data for the first SSL handshake. When a
8229 // CertificateRequest is received for the first time, the handshake will
8230 // be aborted to allow the caller to provide a certificate.
8231 SSLSocketDataProvider ssl_data1(true /* async */,
8232 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8233 ssl_data1.cert_request_info = cert_request.get();
8234 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8235 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8236 session_deps.socket_factory.AddSocketDataProvider(&data1);
8237
8238 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8239 // False Start is not being used, the result of the SSL handshake will be
8240 // returned as part of the SSLClientSocket::Connect() call. This test
8241 // matches the result of a server sending a handshake_failure alert,
8242 // rather than a Finished message, because it requires a client
8243 // certificate and none was supplied.
8244 SSLSocketDataProvider ssl_data2(true /* async */,
8245 net::ERR_SSL_PROTOCOL_ERROR);
8246 ssl_data2.cert_request_info = cert_request.get();
8247 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8248 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8249 session_deps.socket_factory.AddSocketDataProvider(&data2);
8250
8251 // [ssl_]data3 contains the data for the third SSL handshake. When a
8252 // connection to a server fails during an SSL handshake,
8253 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8254 // connection was attempted with TLSv1. This is transparent to the caller
8255 // of the HttpNetworkTransaction. Because this test failure is due to
8256 // requiring a client certificate, this fallback handshake should also
8257 // fail.
8258 SSLSocketDataProvider ssl_data3(true /* async */,
8259 net::ERR_SSL_PROTOCOL_ERROR);
8260 ssl_data3.cert_request_info = cert_request.get();
8261 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8262 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8263 session_deps.socket_factory.AddSocketDataProvider(&data3);
8264
8265 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8266 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8267
[email protected]bd0b6772011-01-11 19:59:308268 // Begin the SSL handshake with the peer. This consumes ssl_data1.
8269 TestCompletionCallback callback;
8270 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8271 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8272
8273 // Complete the SSL handshake, which should abort due to requiring a
8274 // client certificate.
8275 rv = callback.WaitForResult();
8276 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8277
8278 // Indicate that no certificate should be supplied. From the perspective
8279 // of SSLClientCertCache, NULL is just as meaningful as a real
8280 // certificate, so this is the same as supply a
8281 // legitimate-but-unacceptable certificate.
8282 rv = trans->RestartWithCertificate(NULL, &callback);
8283 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8284
8285 // Ensure the certificate was added to the client auth cache before
8286 // allowing the connection to continue restarting.
8287 scoped_refptr<X509Certificate> client_cert;
8288 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8289 &client_cert));
8290 ASSERT_EQ(NULL, client_cert.get());
8291
8292 // Restart the handshake. This will consume ssl_data2, which fails, and
8293 // then consume ssl_data3, which should also fail. The result code is
8294 // checked against what ssl_data3 should return.
8295 rv = callback.WaitForResult();
8296 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8297
8298 // Ensure that the client certificate is removed from the cache on a
8299 // handshake failure.
8300 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8301 &client_cert));
8302}
8303
8304// Ensure that a client certificate is removed from the SSL client auth
8305// cache when:
8306// 1) No proxy is involved.
8307// 2) TLS False Start is enabled.
8308// 3) The initial TLS handshake requests a client certificate.
8309// 4) The client supplies an invalid/unacceptable certificate.
8310TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278311 net::HttpRequestInfo request_info;
8312 request_info.url = GURL("https://www.example.com/");
8313 request_info.method = "GET";
8314 request_info.load_flags = net::LOAD_NORMAL;
8315
[email protected]bd0b6772011-01-11 19:59:308316 SessionDependencies session_deps;
8317
8318 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8319 cert_request->host_and_port = "www.example.com:443";
8320
8321 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8322 // return successfully after reading up to the peer's Certificate message.
8323 // This is to allow the caller to call SSLClientSocket::Write(), which can
8324 // enqueue application data to be sent in the same packet as the
8325 // ChangeCipherSpec and Finished messages.
8326 // The actual handshake will be finished when SSLClientSocket::Read() is
8327 // called, which expects to process the peer's ChangeCipherSpec and
8328 // Finished messages. If there was an error negotiating with the peer,
8329 // such as due to the peer requiring a client certificate when none was
8330 // supplied, the alert sent by the peer won't be processed until Read() is
8331 // called.
8332
8333 // Like the non-False Start case, when a client certificate is requested by
8334 // the peer, the handshake is aborted during the Connect() call.
8335 // [ssl_]data1 represents the initial SSL handshake with the peer.
8336 SSLSocketDataProvider ssl_data1(true /* async */,
8337 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8338 ssl_data1.cert_request_info = cert_request.get();
8339 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8340 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8341 session_deps.socket_factory.AddSocketDataProvider(&data1);
8342
8343 // When a client certificate is supplied, Connect() will not be aborted
8344 // when the peer requests the certificate. Instead, the handshake will
8345 // artificially succeed, allowing the caller to write the HTTP request to
8346 // the socket. The handshake messages are not processed until Read() is
8347 // called, which then detects that the handshake was aborted, due to the
8348 // peer sending a handshake_failure because it requires a client
8349 // certificate.
8350 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8351 ssl_data2.cert_request_info = cert_request.get();
8352 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8353 net::MockRead data2_reads[] = {
8354 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8355 };
8356 net::StaticSocketDataProvider data2(
8357 data2_reads, arraysize(data2_reads), NULL, 0);
8358 session_deps.socket_factory.AddSocketDataProvider(&data2);
8359
8360 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8361 // the data for the SSL handshake once the TLSv1 connection falls back to
8362 // SSLv3. It has the same behaviour as [ssl_]data2.
8363 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8364 ssl_data3.cert_request_info = cert_request.get();
8365 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8366 net::StaticSocketDataProvider data3(
8367 data2_reads, arraysize(data2_reads), NULL, 0);
8368 session_deps.socket_factory.AddSocketDataProvider(&data3);
8369
8370 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8371 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8372
[email protected]bd0b6772011-01-11 19:59:308373 // Begin the initial SSL handshake.
8374 TestCompletionCallback callback;
8375 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8376 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8377
8378 // Complete the SSL handshake, which should abort due to requiring a
8379 // client certificate.
8380 rv = callback.WaitForResult();
8381 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8382
8383 // Indicate that no certificate should be supplied. From the perspective
8384 // of SSLClientCertCache, NULL is just as meaningful as a real
8385 // certificate, so this is the same as supply a
8386 // legitimate-but-unacceptable certificate.
8387 rv = trans->RestartWithCertificate(NULL, &callback);
8388 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8389
8390 // Ensure the certificate was added to the client auth cache before
8391 // allowing the connection to continue restarting.
8392 scoped_refptr<X509Certificate> client_cert;
8393 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8394 &client_cert));
8395 ASSERT_EQ(NULL, client_cert.get());
8396
8397
8398 // Restart the handshake. This will consume ssl_data2, which fails, and
8399 // then consume ssl_data3, which should also fail. The result code is
8400 // checked against what ssl_data3 should return.
8401 rv = callback.WaitForResult();
8402 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8403
8404 // Ensure that the client certificate is removed from the cache on a
8405 // handshake failure.
8406 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8407 &client_cert));
8408}
8409
[email protected]8c405132011-01-11 22:03:188410// Ensure that a client certificate is removed from the SSL client auth
8411// cache when:
8412// 1) An HTTPS proxy is involved.
8413// 3) The HTTPS proxy requests a client certificate.
8414// 4) The client supplies an invalid/unacceptable certificate for the
8415// proxy.
8416// The test is repeated twice, first for connecting to an HTTPS endpoint,
8417// then for connecting to an HTTP endpoint.
8418TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8419 SessionDependencies session_deps(
8420 ProxyService::CreateFixed("https://proxy:70"));
8421 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8422 session_deps.net_log = log.bound().net_log();
8423
8424 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8425 cert_request->host_and_port = "proxy:70";
8426
8427 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8428 // [ssl_]data[1-3]. Rather than represending the endpoint
8429 // (www.example.com:443), they represent failures with the HTTPS proxy
8430 // (proxy:70).
8431 SSLSocketDataProvider ssl_data1(true /* async */,
8432 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8433 ssl_data1.cert_request_info = cert_request.get();
8434 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8435 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8436 session_deps.socket_factory.AddSocketDataProvider(&data1);
8437
8438 SSLSocketDataProvider ssl_data2(true /* async */,
8439 net::ERR_SSL_PROTOCOL_ERROR);
8440 ssl_data2.cert_request_info = cert_request.get();
8441 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8442 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8443 session_deps.socket_factory.AddSocketDataProvider(&data2);
8444
8445 SSLSocketDataProvider ssl_data3(true /* async */,
8446 net::ERR_SSL_PROTOCOL_ERROR);
8447 ssl_data3.cert_request_info = cert_request.get();
8448 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8449 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8450 session_deps.socket_factory.AddSocketDataProvider(&data3);
8451
8452 net::HttpRequestInfo requests[2];
8453 requests[0].url = GURL("https://www.example.com/");
8454 requests[0].method = "GET";
8455 requests[0].load_flags = net::LOAD_NORMAL;
8456
8457 requests[1].url = GURL("http://www.example.com/");
8458 requests[1].method = "GET";
8459 requests[1].load_flags = net::LOAD_NORMAL;
8460
8461 for (size_t i = 0; i < arraysize(requests); ++i) {
8462 session_deps.socket_factory.ResetNextMockIndexes();
8463 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8464 scoped_ptr<HttpNetworkTransaction> trans(
8465 new HttpNetworkTransaction(session));
8466
8467 // Begin the SSL handshake with the proxy.
8468 TestCompletionCallback callback;
8469 int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
8470 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8471
8472 // Complete the SSL handshake, which should abort due to requiring a
8473 // client certificate.
8474 rv = callback.WaitForResult();
8475 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8476
8477 // Indicate that no certificate should be supplied. From the perspective
8478 // of SSLClientCertCache, NULL is just as meaningful as a real
8479 // certificate, so this is the same as supply a
8480 // legitimate-but-unacceptable certificate.
8481 rv = trans->RestartWithCertificate(NULL, &callback);
8482 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8483
8484 // Ensure the certificate was added to the client auth cache before
8485 // allowing the connection to continue restarting.
8486 scoped_refptr<X509Certificate> client_cert;
8487 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8488 &client_cert));
8489 ASSERT_EQ(NULL, client_cert.get());
8490 // Ensure the certificate was NOT cached for the endpoint. This only
8491 // applies to HTTPS requests, but is fine to check for HTTP requests.
8492 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8493 &client_cert));
8494
8495 // Restart the handshake. This will consume ssl_data2, which fails, and
8496 // then consume ssl_data3, which should also fail. The result code is
8497 // checked against what ssl_data3 should return.
8498 rv = callback.WaitForResult();
8499 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8500
8501 // Now that the new handshake has failed, ensure that the client
8502 // certificate was removed from the client auth cache.
8503 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8504 &client_cert));
8505 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8506 &client_cert));
8507 }
8508}
8509
[email protected]89ceba9a2009-03-21 03:46:068510} // namespace net