blob: 0ba698c71cd6f52ee65271509a7aff7ea1c66773 [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]db36938c2009-08-19 21:48:4223#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3324#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5225#include "net/base/test_completion_callback.h"
26#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1227#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0028#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2929#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5730#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5632#include "net/http/http_network_session_peer.h"
[email protected]0877e3d2009-10-17 22:29:5733#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3834#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5235#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5336#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1137#include "net/proxy/proxy_resolver.h"
38#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4439#include "net/socket/client_socket_factory.h"
40#include "net/socket/socket_test_util.h"
41#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5442#include "net/spdy/spdy_framer.h"
43#include "net/spdy/spdy_session.h"
44#include "net/spdy/spdy_session_pool.h"
45#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5246#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1547#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5248
49//-----------------------------------------------------------------------------
50
[email protected]13c8a092010-07-29 06:15:4451namespace {
52
53const string16 kBar(ASCIIToUTF16("bar"));
54const string16 kBar2(ASCIIToUTF16("bar2"));
55const string16 kBar3(ASCIIToUTF16("bar3"));
56const string16 kBaz(ASCIIToUTF16("baz"));
57const string16 kFirst(ASCIIToUTF16("first"));
58const string16 kFoo(ASCIIToUTF16("foo"));
59const string16 kFoo2(ASCIIToUTF16("foo2"));
60const string16 kFoo3(ASCIIToUTF16("foo3"));
61const string16 kFou(ASCIIToUTF16("fou"));
62const string16 kSecond(ASCIIToUTF16("second"));
63const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
64const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
65
66} // namespace
67
[email protected]89ceba9a2009-03-21 03:46:0668namespace net {
69
[email protected]e44de5d2009-06-05 20:12:4570// Helper to manage the lifetimes of the dependencies for a
71// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4472struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5973 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4274 SessionDependencies()
75 : host_resolver(new MockHostResolver),
[email protected]ebeefff32010-09-15 05:10:0276 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:1077 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0878 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5479 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5480 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5981
82 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4583 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4284 : host_resolver(new MockHostResolver),
85 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1086 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0887 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5488 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5489 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5990
[email protected]73c45322010-10-01 23:57:5491 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0992 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4293 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5994 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:5095 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a7ea8832010-07-12 17:54:5496 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:5997};
98
[email protected]228ff742009-06-05 01:19:5999HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]73c45322010-10-01 23:57:54100 return new HttpNetworkSession(session_deps->host_resolver.get(),
[email protected]2db580532010-10-08 14:32:37101 NULL /* dnsrr_resolver */,
[email protected]7ab5bbd12010-10-19 13:33:21102 NULL /* ssl_host_info_factory */,
[email protected]80d6524d2009-08-18 03:58:09103 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42104 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10105 session_deps->ssl_config_service,
[email protected]87bfa3f2010-09-30 14:54:56106 new SpdySessionPool(NULL),
[email protected]06650c52010-06-03 00:49:17107 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44108 NULL,
[email protected]a7ea8832010-07-12 17:54:54109 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14110}
111
[email protected]89836e22008-09-25 20:33:42112class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52113 public:
[email protected]2ff8b312010-04-26 22:20:54114 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50115 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
116 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54117 spdy::SpdyFramer::set_enable_compression_default(false);
118 }
119
[email protected]0e75a732008-10-16 20:36:09120 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50121 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
122 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54123 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09124 // Empty the current queue.
125 MessageLoop::current()->RunAllPending();
126 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50127 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
128 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09129 }
130
[email protected]3d2a59b2008-09-26 19:44:25131 protected:
132 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52133
[email protected]ff007e162009-05-23 09:13:15134 struct SimpleGetHelperResult {
135 int rv;
136 std::string status_line;
137 std::string response_data;
138 };
initial.commit586acc5fe2008-07-26 22:42:52139
[email protected]31a2bfe2010-02-09 08:03:39140 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
141 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15142 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52143
[email protected]228ff742009-06-05 01:19:59144 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40145 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43146 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52147
[email protected]ff007e162009-05-23 09:13:15148 HttpRequestInfo request;
149 request.method = "GET";
150 request.url = GURL("http://www.google.com/");
151 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52152
[email protected]31a2bfe2010-02-09 08:03:39153 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59154 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52155
[email protected]ff007e162009-05-23 09:13:15156 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52157
[email protected]169d0012010-05-10 23:20:12158 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
159 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15160 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52161
[email protected]ff007e162009-05-23 09:13:15162 out.rv = callback.WaitForResult();
163 if (out.rv != OK)
164 return out;
165
166 const HttpResponseInfo* response = trans->GetResponseInfo();
167 EXPECT_TRUE(response != NULL);
168
169 EXPECT_TRUE(response->headers != NULL);
170 out.status_line = response->headers->GetStatusLine();
171
172 rv = ReadTransaction(trans.get(), &out.response_data);
173 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39174 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12175 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
176 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39177 ExpectLogContainsSomewhere(
178 log.entries(), pos,
179 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
180 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15181
[email protected]aecfbf22008-10-16 02:02:47182 return out;
[email protected]ff007e162009-05-23 09:13:15183 }
initial.commit586acc5fe2008-07-26 22:42:52184
[email protected]ff007e162009-05-23 09:13:15185 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
186 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52187
[email protected]ff007e162009-05-23 09:13:15188 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15189};
[email protected]231d5a32008-09-13 00:45:27190
[email protected]15a5ccf82008-10-23 19:57:43191// Fill |str| with a long header list that consumes >= |size| bytes.
192void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19193 const char* row =
194 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
195 const int sizeof_row = strlen(row);
196 const int num_rows = static_cast<int>(
197 ceil(static_cast<float>(size) / sizeof_row));
198 const int sizeof_data = num_rows * sizeof_row;
199 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43200 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51201
[email protected]4ddaf2502008-10-23 18:26:19202 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43203 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19204}
205
[email protected]385a4672009-03-11 22:21:29206// Alternative functions that eliminate randomness and dependency on the local
207// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20208void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29209 static const uint8 bytes[] = {
210 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
211 };
212 static size_t current_byte = 0;
213 for (size_t i = 0; i < n; ++i) {
214 output[i] = bytes[current_byte++];
215 current_byte %= arraysize(bytes);
216 }
217}
218
[email protected]fe2bc6a2009-03-23 16:52:20219void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29220 static const uint8 bytes[] = {
221 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
222 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
223 };
224 static size_t current_byte = 0;
225 for (size_t i = 0; i < n; ++i) {
226 output[i] = bytes[current_byte++];
227 current_byte %= arraysize(bytes);
228 }
229}
230
[email protected]fe2bc6a2009-03-23 16:52:20231std::string MockGetHostName() {
232 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29233}
234
[email protected]e60e47a2010-07-14 03:37:18235template<typename ParentPool>
236class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31237 public:
[email protected]e60e47a2010-07-14 03:37:18238 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
239
[email protected]d80a4322009-08-14 07:07:49240 const std::string last_group_name_received() const {
241 return last_group_name_;
242 }
243
[email protected]684970b2009-08-14 04:54:46244 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49245 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31246 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31247 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46248 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53249 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31250 last_group_name_ = group_name;
251 return ERR_IO_PENDING;
252 }
[email protected]04e5be32009-06-26 20:00:31253 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21254 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31255 virtual void ReleaseSocket(const std::string& group_name,
256 ClientSocket* socket) {}
257 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31258 virtual int IdleSocketCount() const {
259 return 0;
260 }
261 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
262 return 0;
263 }
264 virtual LoadState GetLoadState(const std::string& group_name,
265 const ClientSocketHandle* handle) const {
266 return LOAD_STATE_IDLE;
267 }
[email protected]a796bcec2010-03-22 17:17:26268 virtual base::TimeDelta ConnectionTimeout() const {
269 return base::TimeDelta();
270 }
[email protected]d80a4322009-08-14 07:07:49271
272 private:
[email protected]04e5be32009-06-26 20:00:31273 std::string last_group_name_;
274};
275
[email protected]2d731a32010-04-29 01:04:06276typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11277CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13278typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
279CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06280typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11281CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18282typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
283CaptureGroupNameSSLSocketPool;
284
285template<typename ParentPool>
286CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
287 HttpNetworkSession* session)
288 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
289
290template<>
[email protected]2df19bb2010-08-25 20:13:46291CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
292 HttpNetworkSession* session)
293 : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
294 NULL, NULL) {}
295
296template<>
[email protected]e60e47a2010-07-14 03:37:18297CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
298 HttpNetworkSession* session)
299 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
[email protected]7ab5bbd12010-10-19 13:33:21300 NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11301
[email protected]231d5a32008-09-13 00:45:27302//-----------------------------------------------------------------------------
303
[email protected]dae22c52010-07-30 02:16:35304// This is the expected list of advertised protocols from the browser's NPN
305// list.
306static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
307
308// This is the expected return from a current server advertising SPDY.
309static const char kAlternateProtocolHttpHeader[] =
310 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
311
[email protected]231d5a32008-09-13 00:45:27312TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59313 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40314 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43315 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27316}
317
318TEST_F(HttpNetworkTransactionTest, SimpleGET) {
319 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35320 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
321 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42322 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27323 };
[email protected]31a2bfe2010-02-09 08:03:39324 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
325 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42326 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27327 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
328 EXPECT_EQ("hello world", out.response_data);
329}
330
331// Response with no status line.
332TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
333 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35334 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42335 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27336 };
[email protected]31a2bfe2010-02-09 08:03:39337 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
338 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42339 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27340 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
341 EXPECT_EQ("hello world", out.response_data);
342}
343
344// Allow up to 4 bytes of junk to precede status line.
345TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
346 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35347 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42348 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27349 };
[email protected]31a2bfe2010-02-09 08:03:39350 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
351 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42352 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27353 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
354 EXPECT_EQ("DATA", out.response_data);
355}
356
357// Allow up to 4 bytes of junk to precede status line.
358TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
359 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35360 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42361 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27362 };
[email protected]31a2bfe2010-02-09 08:03:39363 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
364 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42365 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27366 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
367 EXPECT_EQ("DATA", out.response_data);
368}
369
370// Beyond 4 bytes of slop and it should fail to find a status line.
371TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
372 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35373 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42374 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27375 };
[email protected]31a2bfe2010-02-09 08:03:39376 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
377 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42378 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25379 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
380 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27381}
382
383// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
384TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
385 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35386 MockRead("\n"),
387 MockRead("\n"),
388 MockRead("Q"),
389 MockRead("J"),
390 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42391 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27392 };
[email protected]31a2bfe2010-02-09 08:03:39393 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
394 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42395 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27396 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
397 EXPECT_EQ("DATA", out.response_data);
398}
399
400// Close the connection before enough bytes to have a status line.
401TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
402 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35403 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42404 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27405 };
[email protected]31a2bfe2010-02-09 08:03:39406 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
407 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42408 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27409 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
410 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52411}
412
[email protected]f9d44aa2008-09-23 23:57:17413// Simulate a 204 response, lacking a Content-Length header, sent over a
414// persistent connection. The response should still terminate since a 204
415// cannot have a response body.
416TEST_F(HttpNetworkTransactionTest, StopsReading204) {
417 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35418 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
419 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42420 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17421 };
[email protected]31a2bfe2010-02-09 08:03:39422 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
423 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42424 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17425 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
426 EXPECT_EQ("", out.response_data);
427}
428
[email protected]0877e3d2009-10-17 22:29:57429// A simple request using chunked encoding with some extra data after.
430// (Like might be seen in a pipelined response.)
431TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
432 MockRead data_reads[] = {
433 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
434 MockRead("5\r\nHello\r\n"),
435 MockRead("1\r\n"),
436 MockRead(" \r\n"),
437 MockRead("5\r\nworld\r\n"),
438 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
439 MockRead(false, OK),
440 };
[email protected]31a2bfe2010-02-09 08:03:39441 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
442 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57443 EXPECT_EQ(OK, out.rv);
444 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
445 EXPECT_EQ("Hello world", out.response_data);
446}
447
[email protected]9fe44f52010-09-23 18:36:00448// Next tests deal with http://crbug.com/56344.
449
450TEST_F(HttpNetworkTransactionTest,
451 MultipleContentLengthHeadersNoTransferEncoding) {
452 MockRead data_reads[] = {
453 MockRead("HTTP/1.1 200 OK\r\n"),
454 MockRead("Content-Length: 10\r\n"),
455 MockRead("Content-Length: 5\r\n\r\n"),
456 };
457 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
458 arraysize(data_reads));
459 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
460}
461
462TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04463 DuplicateContentLengthHeadersNoTransferEncoding) {
464 MockRead data_reads[] = {
465 MockRead("HTTP/1.1 200 OK\r\n"),
466 MockRead("Content-Length: 5\r\n"),
467 MockRead("Content-Length: 5\r\n\r\n"),
468 MockRead("Hello"),
469 };
470 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
471 arraysize(data_reads));
472 EXPECT_EQ(OK, out.rv);
473 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
474 EXPECT_EQ("Hello", out.response_data);
475}
476
477TEST_F(HttpNetworkTransactionTest,
478 ComplexContentLengthHeadersNoTransferEncoding) {
479 // More than 2 dupes.
480 {
481 MockRead data_reads[] = {
482 MockRead("HTTP/1.1 200 OK\r\n"),
483 MockRead("Content-Length: 5\r\n"),
484 MockRead("Content-Length: 5\r\n"),
485 MockRead("Content-Length: 5\r\n\r\n"),
486 MockRead("Hello"),
487 };
488 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
489 arraysize(data_reads));
490 EXPECT_EQ(OK, out.rv);
491 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
492 EXPECT_EQ("Hello", out.response_data);
493 }
494 // HTTP/1.0
495 {
496 MockRead data_reads[] = {
497 MockRead("HTTP/1.0 200 OK\r\n"),
498 MockRead("Content-Length: 5\r\n"),
499 MockRead("Content-Length: 5\r\n"),
500 MockRead("Content-Length: 5\r\n\r\n"),
501 MockRead("Hello"),
502 };
503 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
504 arraysize(data_reads));
505 EXPECT_EQ(OK, out.rv);
506 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
507 EXPECT_EQ("Hello", out.response_data);
508 }
509 // 2 dupes and one mismatched.
510 {
511 MockRead data_reads[] = {
512 MockRead("HTTP/1.1 200 OK\r\n"),
513 MockRead("Content-Length: 10\r\n"),
514 MockRead("Content-Length: 10\r\n"),
515 MockRead("Content-Length: 5\r\n\r\n"),
516 };
517 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
518 arraysize(data_reads));
519 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
520 }
521}
522
523TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00524 MultipleContentLengthHeadersTransferEncoding) {
525 MockRead data_reads[] = {
526 MockRead("HTTP/1.1 200 OK\r\n"),
527 MockRead("Content-Length: 666\r\n"),
528 MockRead("Content-Length: 1337\r\n"),
529 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
530 MockRead("5\r\nHello\r\n"),
531 MockRead("1\r\n"),
532 MockRead(" \r\n"),
533 MockRead("5\r\nworld\r\n"),
534 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
535 MockRead(false, OK),
536 };
537 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
538 arraysize(data_reads));
539 EXPECT_EQ(OK, out.rv);
540 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
541 EXPECT_EQ("Hello world", out.response_data);
542}
543
[email protected]ef0faf2e72009-03-05 23:27:23544// Do a request using the HEAD method. Verify that we don't try to read the
545// message body (since HEAD has none).
546TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59547 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40548 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43549 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23550
[email protected]1c773ea12009-04-28 19:58:42551 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23552 request.method = "HEAD";
553 request.url = GURL("http://www.google.com/");
554 request.load_flags = 0;
555
556 MockWrite data_writes1[] = {
557 MockWrite("HEAD / HTTP/1.1\r\n"
558 "Host: www.google.com\r\n"
559 "Connection: keep-alive\r\n"
560 "Content-Length: 0\r\n\r\n"),
561 };
562 MockRead data_reads1[] = {
563 MockRead("HTTP/1.1 404 Not Found\r\n"),
564 MockRead("Server: Blah\r\n"),
565 MockRead("Content-Length: 1234\r\n\r\n"),
566
567 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42568 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23569 };
570
[email protected]31a2bfe2010-02-09 08:03:39571 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
572 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59573 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23574
575 TestCompletionCallback callback1;
576
[email protected]5a1d7ca2010-04-28 20:12:27577 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42578 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23579
580 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42581 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23582
[email protected]1c773ea12009-04-28 19:58:42583 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23584 EXPECT_FALSE(response == NULL);
585
586 // Check that the headers got parsed.
587 EXPECT_TRUE(response->headers != NULL);
588 EXPECT_EQ(1234, response->headers->GetContentLength());
589 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
590
591 std::string server_header;
592 void* iter = NULL;
593 bool has_server_header = response->headers->EnumerateHeader(
594 &iter, "Server", &server_header);
595 EXPECT_TRUE(has_server_header);
596 EXPECT_EQ("Blah", server_header);
597
598 // Reading should give EOF right away, since there is no message body
599 // (despite non-zero content-length).
600 std::string response_data;
601 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42602 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23603 EXPECT_EQ("", response_data);
604}
605
initial.commit586acc5fe2008-07-26 22:42:52606TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59607 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27608 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52609
610 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35611 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
612 MockRead("hello"),
613 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
614 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42615 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52616 };
[email protected]31a2bfe2010-02-09 08:03:39617 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59618 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52619
[email protected]0b0bf032010-09-21 18:08:50620 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52621 "hello", "world"
622 };
623
624 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43625 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52626
[email protected]1c773ea12009-04-28 19:58:42627 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52628 request.method = "GET";
629 request.url = GURL("http://www.google.com/");
630 request.load_flags = 0;
631
632 TestCompletionCallback callback;
633
[email protected]5a1d7ca2010-04-28 20:12:27634 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42635 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52636
637 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42638 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52639
[email protected]1c773ea12009-04-28 19:58:42640 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52641 EXPECT_TRUE(response != NULL);
642
643 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25644 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52645
646 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57647 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42648 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25649 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52650 }
651}
652
653TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59654 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40655 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43656 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52657
[email protected]1c773ea12009-04-28 19:58:42658 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52659 request.method = "POST";
660 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42661 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52662 request.upload_data->AppendBytes("foo", 3);
663 request.load_flags = 0;
664
665 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35666 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
667 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
668 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42669 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52670 };
[email protected]31a2bfe2010-02-09 08:03:39671 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59672 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52673
674 TestCompletionCallback callback;
675
[email protected]5a1d7ca2010-04-28 20:12:27676 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42677 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52678
679 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42680 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52681
[email protected]1c773ea12009-04-28 19:58:42682 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52683 EXPECT_TRUE(response != NULL);
684
685 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25686 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52687
688 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57689 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42690 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25691 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52692}
693
[email protected]3a2d3662009-03-27 03:49:14694// This test is almost the same as Ignores100 above, but the response contains
695// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57696// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14697TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59698 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40699 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43700 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14701
[email protected]1c773ea12009-04-28 19:58:42702 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14703 request.method = "GET";
704 request.url = GURL("http://www.foo.com/");
705 request.load_flags = 0;
706
707 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57708 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
709 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14710 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42711 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14712 };
[email protected]31a2bfe2010-02-09 08:03:39713 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59714 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14715
716 TestCompletionCallback callback;
717
[email protected]5a1d7ca2010-04-28 20:12:27718 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42719 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14720
721 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42722 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14723
[email protected]1c773ea12009-04-28 19:58:42724 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14725 EXPECT_TRUE(response != NULL);
726
727 EXPECT_TRUE(response->headers != NULL);
728 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
729
730 std::string response_data;
731 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42732 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14733 EXPECT_EQ("hello world", response_data);
734}
735
[email protected]ee9410e72010-01-07 01:42:38736TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
737 SessionDependencies session_deps;
738 scoped_ptr<HttpTransaction> trans(
739 new HttpNetworkTransaction(CreateSession(&session_deps)));
740
741 HttpRequestInfo request;
742 request.method = "POST";
743 request.url = GURL("http://www.foo.com/");
744 request.load_flags = 0;
745
746 MockRead data_reads[] = {
747 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
748 MockRead(true, 0),
749 };
[email protected]31a2bfe2010-02-09 08:03:39750 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38751 session_deps.socket_factory.AddSocketDataProvider(&data);
752
753 TestCompletionCallback callback;
754
[email protected]5a1d7ca2010-04-28 20:12:27755 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38756 EXPECT_EQ(ERR_IO_PENDING, rv);
757
758 rv = callback.WaitForResult();
759 EXPECT_EQ(OK, rv);
760
761 std::string response_data;
762 rv = ReadTransaction(trans.get(), &response_data);
763 EXPECT_EQ(OK, rv);
764 EXPECT_EQ("", response_data);
765}
766
767TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
768 SessionDependencies session_deps;
769 scoped_ptr<HttpTransaction> trans(
770 new HttpNetworkTransaction(CreateSession(&session_deps)));
771
772 HttpRequestInfo request;
773 request.method = "POST";
774 request.url = GURL("http://www.foo.com/");
775 request.load_flags = 0;
776
777 MockRead data_reads[] = {
778 MockRead(true, 0),
779 };
[email protected]31a2bfe2010-02-09 08:03:39780 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38781 session_deps.socket_factory.AddSocketDataProvider(&data);
782
783 TestCompletionCallback callback;
784
[email protected]5a1d7ca2010-04-28 20:12:27785 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38786 EXPECT_EQ(ERR_IO_PENDING, rv);
787
788 rv = callback.WaitForResult();
789 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
790}
791
[email protected]3d2a59b2008-09-26 19:44:25792// read_failure specifies a read failure that should cause the network
793// transaction to resend the request.
794void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
795 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59796 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27797 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52798
[email protected]1c773ea12009-04-28 19:58:42799 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52800 request.method = "GET";
801 request.url = GURL("http://www.foo.com/");
802 request.load_flags = 0;
803
804 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35805 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
806 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25807 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52808 };
[email protected]31a2bfe2010-02-09 08:03:39809 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59810 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52811
812 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35813 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
814 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42815 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52816 };
[email protected]31a2bfe2010-02-09 08:03:39817 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59818 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52819
820 const char* kExpectedResponseData[] = {
821 "hello", "world"
822 };
823
824 for (int i = 0; i < 2; ++i) {
825 TestCompletionCallback callback;
826
[email protected]5695b8c2009-09-30 21:36:43827 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52828
[email protected]5a1d7ca2010-04-28 20:12:27829 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42830 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52831
832 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42833 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52834
[email protected]1c773ea12009-04-28 19:58:42835 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52836 EXPECT_TRUE(response != NULL);
837
838 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25839 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52840
841 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57842 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42843 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25844 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52845 }
846}
[email protected]3d2a59b2008-09-26 19:44:25847
848TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42849 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25850 KeepAliveConnectionResendRequestTest(read_failure);
851}
852
853TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42854 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25855 KeepAliveConnectionResendRequestTest(read_failure);
856}
857
858TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59859 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40860 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43861 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25862
[email protected]1c773ea12009-04-28 19:58:42863 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25864 request.method = "GET";
865 request.url = GURL("http://www.google.com/");
866 request.load_flags = 0;
867
868 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42869 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35870 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
871 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42872 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25873 };
[email protected]31a2bfe2010-02-09 08:03:39874 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59875 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25876
877 TestCompletionCallback callback;
878
[email protected]5a1d7ca2010-04-28 20:12:27879 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42880 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25881
882 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42883 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25884
[email protected]1c773ea12009-04-28 19:58:42885 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25886 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25887}
888
889// What do various browsers do when the server closes a non-keepalive
890// connection without sending any response header or body?
891//
892// IE7: error page
893// Safari 3.1.2 (Windows): error page
894// Firefox 3.0.1: blank page
895// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42896// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
897// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25898TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
899 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42900 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35901 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
902 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42903 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25904 };
[email protected]31a2bfe2010-02-09 08:03:39905 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
906 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42907 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25908}
[email protected]038e9a32008-10-08 22:40:16909
[email protected]0b0bf032010-09-21 18:08:50910// Test that we correctly reuse a keep-alive connection after not explicitly
911// reading the body.
912TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13913 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27914 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]fc31d6a42010-06-24 18:05:13915
916 HttpRequestInfo request;
917 request.method = "GET";
918 request.url = GURL("http://www.foo.com/");
919 request.load_flags = 0;
920
[email protected]0b0bf032010-09-21 18:08:50921 // Note that because all these reads happen in the same
922 // StaticSocketDataProvider, it shows that the same socket is being reused for
923 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13924 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50925 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
926 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13927 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50928 MockRead("HTTP/1.1 302 Found\r\n"
929 "Content-Length: 0\r\n\r\n"),
930 MockRead("HTTP/1.1 302 Found\r\n"
931 "Content-Length: 5\r\n\r\n"
932 "hello"),
933 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
934 "Content-Length: 0\r\n\r\n"),
935 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
936 "Content-Length: 5\r\n\r\n"
937 "hello"),
[email protected]fc31d6a42010-06-24 18:05:13938 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
939 MockRead("hello"),
940 };
941 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
942 session_deps.socket_factory.AddSocketDataProvider(&data1);
943
944 MockRead data2_reads[] = {
945 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
946 };
947 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
948 session_deps.socket_factory.AddSocketDataProvider(&data2);
949
[email protected]0b0bf032010-09-21 18:08:50950 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
951 std::string response_lines[kNumUnreadBodies];
952
953 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:13954 TestCompletionCallback callback;
955
956 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
957
958 int rv = trans->Start(&request, &callback, BoundNetLog());
959 EXPECT_EQ(ERR_IO_PENDING, rv);
960
961 rv = callback.WaitForResult();
962 EXPECT_EQ(OK, rv);
963
964 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:50965 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:13966
[email protected]0b0bf032010-09-21 18:08:50967 ASSERT_TRUE(response->headers != NULL);
968 response_lines[i] = response->headers->GetStatusLine();
969
970 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:13971 }
[email protected]0b0bf032010-09-21 18:08:50972
973 const char* const kStatusLines[] = {
974 "HTTP/1.1 204 No Content",
975 "HTTP/1.1 205 Reset Content",
976 "HTTP/1.1 304 Not Modified",
977 "HTTP/1.1 302 Found",
978 "HTTP/1.1 302 Found",
979 "HTTP/1.1 301 Moved Permanently",
980 "HTTP/1.1 301 Moved Permanently",
981 };
982
983 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
984 forgot_to_update_kStatusLines);
985
986 for (int i = 0; i < kNumUnreadBodies; ++i)
987 EXPECT_EQ(kStatusLines[i], response_lines[i]);
988
989 TestCompletionCallback callback;
990 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
991 int rv = trans->Start(&request, &callback, BoundNetLog());
992 EXPECT_EQ(ERR_IO_PENDING, rv);
993 rv = callback.WaitForResult();
994 EXPECT_EQ(OK, rv);
995 const HttpResponseInfo* response = trans->GetResponseInfo();
996 ASSERT_TRUE(response != NULL);
997 ASSERT_TRUE(response->headers != NULL);
998 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
999 std::string response_data;
1000 rv = ReadTransaction(trans.get(), &response_data);
1001 EXPECT_EQ(OK, rv);
1002 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131003}
1004
[email protected]038e9a32008-10-08 22:40:161005// Test the request-challenge-retry sequence for basic auth.
1006// (basic auth is the easiest to mock, because it has no randomness).
1007TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:591008 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401009 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431010 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161011
[email protected]1c773ea12009-04-28 19:58:421012 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161013 request.method = "GET";
1014 request.url = GURL("http://www.google.com/");
1015 request.load_flags = 0;
1016
[email protected]f9ee6b52008-11-08 06:46:231017 MockWrite data_writes1[] = {
1018 MockWrite("GET / HTTP/1.1\r\n"
1019 "Host: www.google.com\r\n"
1020 "Connection: keep-alive\r\n\r\n"),
1021 };
1022
[email protected]038e9a32008-10-08 22:40:161023 MockRead data_reads1[] = {
1024 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1025 // Give a couple authenticate options (only the middle one is actually
1026 // supported).
[email protected]22927ad2009-09-21 19:56:191027 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161028 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1029 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1030 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1031 // Large content-length -- won't matter, as connection will be reset.
1032 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421033 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161034 };
1035
1036 // After calling trans->RestartWithAuth(), this is the request we should
1037 // be issuing -- the final header line contains the credentials.
1038 MockWrite data_writes2[] = {
1039 MockWrite("GET / HTTP/1.1\r\n"
1040 "Host: www.google.com\r\n"
1041 "Connection: keep-alive\r\n"
1042 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1043 };
1044
1045 // Lastly, the server responds with the actual content.
1046 MockRead data_reads2[] = {
1047 MockRead("HTTP/1.0 200 OK\r\n"),
1048 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1049 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421050 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161051 };
1052
[email protected]31a2bfe2010-02-09 08:03:391053 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1054 data_writes1, arraysize(data_writes1));
1055 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1056 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591057 session_deps.socket_factory.AddSocketDataProvider(&data1);
1058 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161059
1060 TestCompletionCallback callback1;
1061
[email protected]5a1d7ca2010-04-28 20:12:271062 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421063 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161064
1065 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421066 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161067
[email protected]1c773ea12009-04-28 19:58:421068 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161069 EXPECT_FALSE(response == NULL);
1070
1071 // The password prompt info should have been set in response->auth_challenge.
1072 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1073
[email protected]71e4573a2009-05-21 22:03:001074 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161075 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1076 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1077
1078 TestCompletionCallback callback2;
1079
[email protected]13c8a092010-07-29 06:15:441080 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421081 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161082
1083 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421084 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161085
1086 response = trans->GetResponseInfo();
1087 EXPECT_FALSE(response == NULL);
1088 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1089 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161090}
1091
[email protected]861fcd52009-08-26 02:33:461092TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
1093 SessionDependencies session_deps;
1094 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431095 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:461096
1097 HttpRequestInfo request;
1098 request.method = "GET";
1099 request.url = GURL("http://www.google.com/");
1100 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1101
1102 MockWrite data_writes[] = {
1103 MockWrite("GET / HTTP/1.1\r\n"
1104 "Host: www.google.com\r\n"
1105 "Connection: keep-alive\r\n\r\n"),
1106 };
1107
1108 MockRead data_reads[] = {
1109 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1110 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1111 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1112 // Large content-length -- won't matter, as connection will be reset.
1113 MockRead("Content-Length: 10000\r\n\r\n"),
1114 MockRead(false, ERR_FAILED),
1115 };
1116
[email protected]31a2bfe2010-02-09 08:03:391117 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1118 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591119 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461120 TestCompletionCallback callback;
1121
[email protected]5a1d7ca2010-04-28 20:12:271122 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461123 EXPECT_EQ(ERR_IO_PENDING, rv);
1124
1125 rv = callback.WaitForResult();
1126 EXPECT_EQ(0, rv);
1127
1128 const HttpResponseInfo* response = trans->GetResponseInfo();
1129 ASSERT_FALSE(response == NULL);
1130 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1131}
1132
[email protected]2d2697f92009-02-18 21:00:321133// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1134// connection.
1135TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591136 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501137 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321138
[email protected]1c773ea12009-04-28 19:58:421139 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321140 request.method = "GET";
1141 request.url = GURL("http://www.google.com/");
1142 request.load_flags = 0;
1143
1144 MockWrite data_writes1[] = {
1145 MockWrite("GET / HTTP/1.1\r\n"
1146 "Host: www.google.com\r\n"
1147 "Connection: keep-alive\r\n\r\n"),
1148
1149 // After calling trans->RestartWithAuth(), this is the request we should
1150 // be issuing -- the final header line contains the credentials.
1151 MockWrite("GET / HTTP/1.1\r\n"
1152 "Host: www.google.com\r\n"
1153 "Connection: keep-alive\r\n"
1154 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1155 };
1156
1157 MockRead data_reads1[] = {
1158 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1159 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1160 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1161 MockRead("Content-Length: 14\r\n\r\n"),
1162 MockRead("Unauthorized\r\n"),
1163
1164 // Lastly, the server responds with the actual content.
1165 MockRead("HTTP/1.1 200 OK\r\n"),
1166 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501167 MockRead("Content-Length: 5\r\n\r\n"),
1168 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321169 };
1170
[email protected]31a2bfe2010-02-09 08:03:391171 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1172 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591173 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321174
1175 TestCompletionCallback callback1;
1176
[email protected]0b0bf032010-09-21 18:08:501177 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271178 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421179 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321180
1181 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421182 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321183
[email protected]1c773ea12009-04-28 19:58:421184 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321185 EXPECT_FALSE(response == NULL);
1186
1187 // The password prompt info should have been set in response->auth_challenge.
1188 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1189
[email protected]71e4573a2009-05-21 22:03:001190 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321191 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1192 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1193
1194 TestCompletionCallback callback2;
1195
[email protected]13c8a092010-07-29 06:15:441196 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421197 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321198
1199 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421200 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321201
1202 response = trans->GetResponseInfo();
1203 EXPECT_FALSE(response == NULL);
1204 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501205 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321206}
1207
1208// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1209// connection and with no response body to drain.
1210TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591211 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501212 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321213
[email protected]1c773ea12009-04-28 19:58:421214 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321215 request.method = "GET";
1216 request.url = GURL("http://www.google.com/");
1217 request.load_flags = 0;
1218
1219 MockWrite data_writes1[] = {
1220 MockWrite("GET / HTTP/1.1\r\n"
1221 "Host: www.google.com\r\n"
1222 "Connection: keep-alive\r\n\r\n"),
1223
1224 // After calling trans->RestartWithAuth(), this is the request we should
1225 // be issuing -- the final header line contains the credentials.
1226 MockWrite("GET / HTTP/1.1\r\n"
1227 "Host: www.google.com\r\n"
1228 "Connection: keep-alive\r\n"
1229 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1230 };
1231
[email protected]2d2697f92009-02-18 21:00:321232 MockRead data_reads1[] = {
1233 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1234 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311235 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321236
1237 // Lastly, the server responds with the actual content.
1238 MockRead("HTTP/1.1 200 OK\r\n"),
1239 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501240 MockRead("Content-Length: 5\r\n\r\n"),
1241 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321242 };
1243
[email protected]31a2bfe2010-02-09 08:03:391244 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1245 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591246 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321247
1248 TestCompletionCallback callback1;
1249
[email protected]0b0bf032010-09-21 18:08:501250 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271251 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421252 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321253
1254 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421255 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321256
[email protected]1c773ea12009-04-28 19:58:421257 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321258 EXPECT_FALSE(response == NULL);
1259
1260 // The password prompt info should have been set in response->auth_challenge.
1261 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1262
[email protected]71e4573a2009-05-21 22:03:001263 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321264 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1265 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1266
1267 TestCompletionCallback callback2;
1268
[email protected]13c8a092010-07-29 06:15:441269 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421270 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321271
1272 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421273 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321274
1275 response = trans->GetResponseInfo();
1276 EXPECT_FALSE(response == NULL);
1277 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501278 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321279}
1280
1281// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1282// connection and with a large response body to drain.
1283TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591284 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501285 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321286
[email protected]1c773ea12009-04-28 19:58:421287 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321288 request.method = "GET";
1289 request.url = GURL("http://www.google.com/");
1290 request.load_flags = 0;
1291
1292 MockWrite data_writes1[] = {
1293 MockWrite("GET / HTTP/1.1\r\n"
1294 "Host: www.google.com\r\n"
1295 "Connection: keep-alive\r\n\r\n"),
1296
1297 // After calling trans->RestartWithAuth(), this is the request we should
1298 // be issuing -- the final header line contains the credentials.
1299 MockWrite("GET / HTTP/1.1\r\n"
1300 "Host: www.google.com\r\n"
1301 "Connection: keep-alive\r\n"
1302 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1303 };
1304
1305 // Respond with 5 kb of response body.
1306 std::string large_body_string("Unauthorized");
1307 large_body_string.append(5 * 1024, ' ');
1308 large_body_string.append("\r\n");
1309
1310 MockRead data_reads1[] = {
1311 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1312 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1313 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1314 // 5134 = 12 + 5 * 1024 + 2
1315 MockRead("Content-Length: 5134\r\n\r\n"),
1316 MockRead(true, large_body_string.data(), large_body_string.size()),
1317
1318 // Lastly, the server responds with the actual content.
1319 MockRead("HTTP/1.1 200 OK\r\n"),
1320 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501321 MockRead("Content-Length: 5\r\n\r\n"),
1322 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321323 };
1324
[email protected]31a2bfe2010-02-09 08:03:391325 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1326 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591327 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321328
1329 TestCompletionCallback callback1;
1330
[email protected]0b0bf032010-09-21 18:08:501331 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271332 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421333 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321334
1335 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421336 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321337
[email protected]1c773ea12009-04-28 19:58:421338 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321339 EXPECT_FALSE(response == NULL);
1340
1341 // The password prompt info should have been set in response->auth_challenge.
1342 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1343
[email protected]71e4573a2009-05-21 22:03:001344 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321345 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1346 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1347
1348 TestCompletionCallback callback2;
1349
[email protected]13c8a092010-07-29 06:15:441350 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421351 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321352
1353 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421354 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321355
1356 response = trans->GetResponseInfo();
1357 EXPECT_FALSE(response == NULL);
1358 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501359 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321360}
1361
1362// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311363// connection, but the server gets impatient and closes the connection.
1364TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1365 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501366 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]11203f012009-11-12 23:02:311367
1368 HttpRequestInfo request;
1369 request.method = "GET";
1370 request.url = GURL("http://www.google.com/");
1371 request.load_flags = 0;
1372
1373 MockWrite data_writes1[] = {
1374 MockWrite("GET / HTTP/1.1\r\n"
1375 "Host: www.google.com\r\n"
1376 "Connection: keep-alive\r\n\r\n"),
1377 // This simulates the seemingly successful write to a closed connection
1378 // if the bug is not fixed.
1379 MockWrite("GET / HTTP/1.1\r\n"
1380 "Host: www.google.com\r\n"
1381 "Connection: keep-alive\r\n"
1382 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1383 };
1384
1385 MockRead data_reads1[] = {
1386 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1387 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1388 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1389 MockRead("Content-Length: 14\r\n\r\n"),
1390 // Tell MockTCPClientSocket to simulate the server closing the connection.
1391 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1392 MockRead("Unauthorized\r\n"),
1393 MockRead(false, OK), // The server closes the connection.
1394 };
1395
1396 // After calling trans->RestartWithAuth(), this is the request we should
1397 // be issuing -- the final header line contains the credentials.
1398 MockWrite data_writes2[] = {
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 // Lastly, the server responds with the actual content.
1406 MockRead data_reads2[] = {
1407 MockRead("HTTP/1.1 200 OK\r\n"),
1408 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501409 MockRead("Content-Length: 5\r\n\r\n"),
1410 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311411 };
1412
[email protected]31a2bfe2010-02-09 08:03:391413 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1414 data_writes1, arraysize(data_writes1));
1415 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1416 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311417 session_deps.socket_factory.AddSocketDataProvider(&data1);
1418 session_deps.socket_factory.AddSocketDataProvider(&data2);
1419
1420 TestCompletionCallback callback1;
1421
[email protected]0b0bf032010-09-21 18:08:501422 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271423 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311424 EXPECT_EQ(ERR_IO_PENDING, rv);
1425
1426 rv = callback1.WaitForResult();
1427 EXPECT_EQ(OK, rv);
1428
1429 const HttpResponseInfo* response = trans->GetResponseInfo();
1430 EXPECT_FALSE(response == NULL);
1431
1432 // The password prompt info should have been set in response->auth_challenge.
1433 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1434
1435 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1436 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1437 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1438
1439 TestCompletionCallback callback2;
1440
[email protected]13c8a092010-07-29 06:15:441441 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311442 EXPECT_EQ(ERR_IO_PENDING, rv);
1443
1444 rv = callback2.WaitForResult();
1445 EXPECT_EQ(OK, rv);
1446
1447 response = trans->GetResponseInfo();
1448 ASSERT_FALSE(response == NULL);
1449 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501450 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311451}
1452
[email protected]394816e92010-08-03 07:38:591453// Test the request-challenge-retry sequence for basic auth, over a connection
1454// that requires a restart when setting up an SSL tunnel.
1455TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1456 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001457 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]394816e92010-08-03 07:38:591458 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1459 session_deps.net_log = log.bound().net_log();
1460 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1461
[email protected]394816e92010-08-03 07:38:591462 HttpRequestInfo request;
1463 request.method = "GET";
1464 request.url = GURL("https://www.google.com/");
1465 // when the no authentication data flag is set.
1466 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1467
1468 // Since we have proxy, should try to establish tunnel.
1469 MockWrite data_writes1[] = {
1470 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1471 "Host: www.google.com\r\n"
1472 "Proxy-Connection: keep-alive\r\n\r\n"),
1473
1474 // After calling trans->RestartWithAuth(), this is the request we should
1475 // be issuing -- the final header line contains the credentials.
1476 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1477 "Host: www.google.com\r\n"
1478 "Proxy-Connection: keep-alive\r\n"
1479 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1480
1481 MockWrite("GET / HTTP/1.1\r\n"
1482 "Host: www.google.com\r\n"
1483 "Connection: keep-alive\r\n\r\n"),
1484 };
1485
1486 // The proxy responds to the connect with a 407, using a persistent
1487 // connection.
1488 MockRead data_reads1[] = {
1489 // No credentials.
1490 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1491 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1492 MockRead("Proxy-Connection: close\r\n\r\n"),
1493
1494 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1495
1496 MockRead("HTTP/1.1 200 OK\r\n"),
1497 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501498 MockRead("Content-Length: 5\r\n\r\n"),
1499 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591500 };
1501
1502 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1503 data_writes1, arraysize(data_writes1));
1504 session_deps.socket_factory.AddSocketDataProvider(&data1);
1505 SSLSocketDataProvider ssl(true, OK);
1506 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1507
1508 TestCompletionCallback callback1;
1509
[email protected]0b0bf032010-09-21 18:08:501510 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1511
[email protected]394816e92010-08-03 07:38:591512 int rv = trans->Start(&request, &callback1, log.bound());
1513 EXPECT_EQ(ERR_IO_PENDING, rv);
1514
1515 rv = callback1.WaitForResult();
1516 EXPECT_EQ(OK, rv);
1517 size_t pos = ExpectLogContainsSomewhere(
1518 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1519 NetLog::PHASE_NONE);
1520 ExpectLogContainsSomewhere(
1521 log.entries(), pos,
1522 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1523 NetLog::PHASE_NONE);
1524
1525 const HttpResponseInfo* response = trans->GetResponseInfo();
1526 ASSERT_FALSE(response == NULL);
1527
1528 EXPECT_EQ(407, response->headers->response_code());
1529 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1530
1531 // The password prompt info should have been set in response->auth_challenge.
1532 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1533
1534 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1535 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1536 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1537
1538 TestCompletionCallback callback2;
1539
1540 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1541 EXPECT_EQ(ERR_IO_PENDING, rv);
1542
1543 rv = callback2.WaitForResult();
1544 EXPECT_EQ(OK, rv);
1545
1546 response = trans->GetResponseInfo();
1547 ASSERT_FALSE(response == NULL);
1548
1549 EXPECT_TRUE(response->headers->IsKeepAlive());
1550 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501551 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591552 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1553
1554 // The password prompt info should not be set.
1555 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501556
1557 trans.reset();
1558 session->FlushSocketPools();
[email protected]394816e92010-08-03 07:38:591559}
1560
[email protected]11203f012009-11-12 23:02:311561// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321562// proxy connection, when setting up an SSL tunnel.
1563TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1564 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001565 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541566 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1567 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591568 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321569
[email protected]5695b8c2009-09-30 21:36:431570 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321571
[email protected]1c773ea12009-04-28 19:58:421572 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321573 request.method = "GET";
1574 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461575 // Ensure that proxy authentication is attempted even
1576 // when the no authentication data flag is set.
1577 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321578
1579 // Since we have proxy, should try to establish tunnel.
1580 MockWrite data_writes1[] = {
1581 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451582 "Host: www.google.com\r\n"
1583 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321584
1585 // After calling trans->RestartWithAuth(), this is the request we should
1586 // be issuing -- the final header line contains the credentials.
1587 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1588 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451589 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321590 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1591 };
1592
1593 // The proxy responds to the connect with a 407, using a persistent
1594 // connection.
1595 MockRead data_reads1[] = {
1596 // No credentials.
1597 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1598 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1599 MockRead("Content-Length: 10\r\n\r\n"),
1600 MockRead("0123456789"),
1601
1602 // Wrong credentials (wrong password).
1603 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1604 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1605 MockRead("Content-Length: 10\r\n\r\n"),
1606 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421607 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321608 };
1609
[email protected]31a2bfe2010-02-09 08:03:391610 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1611 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591612 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321613
1614 TestCompletionCallback callback1;
1615
[email protected]dbb83db2010-05-11 18:13:391616 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421617 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321618
1619 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421620 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391621 size_t pos = ExpectLogContainsSomewhere(
1622 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1623 NetLog::PHASE_NONE);
1624 ExpectLogContainsSomewhere(
1625 log.entries(), pos,
1626 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1627 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321628
[email protected]1c773ea12009-04-28 19:58:421629 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321630 EXPECT_FALSE(response == NULL);
1631
1632 EXPECT_TRUE(response->headers->IsKeepAlive());
1633 EXPECT_EQ(407, response->headers->response_code());
1634 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421635 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321636
1637 // The password prompt info should have been set in response->auth_challenge.
1638 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1639
[email protected]71e4573a2009-05-21 22:03:001640 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321641 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1642 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1643
1644 TestCompletionCallback callback2;
1645
1646 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441647 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421648 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321649
1650 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421651 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321652
1653 response = trans->GetResponseInfo();
1654 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);
[email protected]e772db3f2010-07-12 18:11:131667
[email protected]e60e47a2010-07-14 03:37:181668 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1669 // out of scope.
1670 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321671}
1672
[email protected]a8e9b162009-03-12 00:06:441673// Test that we don't read the response body when we fail to establish a tunnel,
1674// even if the user cancels the proxy's auth attempt.
1675TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1676 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001677 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441678
[email protected]e44de5d2009-06-05 20:12:451679 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441680
[email protected]5695b8c2009-09-30 21:36:431681 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441682
[email protected]1c773ea12009-04-28 19:58:421683 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441684 request.method = "GET";
1685 request.url = GURL("https://www.google.com/");
1686 request.load_flags = 0;
1687
1688 // Since we have proxy, should try to establish tunnel.
1689 MockWrite data_writes[] = {
1690 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451691 "Host: www.google.com\r\n"
1692 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441693 };
1694
1695 // The proxy responds to the connect with a 407.
1696 MockRead data_reads[] = {
1697 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1698 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1699 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421700 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441701 };
1702
[email protected]31a2bfe2010-02-09 08:03:391703 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1704 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591705 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441706
1707 TestCompletionCallback callback;
1708
[email protected]5a1d7ca2010-04-28 20:12:271709 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421710 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441711
1712 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421713 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441714
[email protected]1c773ea12009-04-28 19:58:421715 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441716 EXPECT_FALSE(response == NULL);
1717
1718 EXPECT_TRUE(response->headers->IsKeepAlive());
1719 EXPECT_EQ(407, response->headers->response_code());
1720 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421721 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441722
1723 std::string response_data;
1724 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421725 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181726
1727 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1728 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441729}
1730
[email protected]8fdbcd22010-05-05 02:54:521731// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1732// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1733TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1734 // We are using a DIRECT connection (i.e. no proxy) for this session.
1735 SessionDependencies session_deps;
1736 scoped_ptr<HttpTransaction> trans(
1737 new HttpNetworkTransaction(CreateSession(&session_deps)));
1738
1739 HttpRequestInfo request;
1740 request.method = "GET";
1741 request.url = GURL("http://www.google.com/");
1742 request.load_flags = 0;
1743
1744 MockWrite data_writes1[] = {
1745 MockWrite("GET / HTTP/1.1\r\n"
1746 "Host: www.google.com\r\n"
1747 "Connection: keep-alive\r\n\r\n"),
1748 };
1749
1750 MockRead data_reads1[] = {
1751 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1752 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1753 // Large content-length -- won't matter, as connection will be reset.
1754 MockRead("Content-Length: 10000\r\n\r\n"),
1755 MockRead(false, ERR_FAILED),
1756 };
1757
1758 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1759 data_writes1, arraysize(data_writes1));
1760 session_deps.socket_factory.AddSocketDataProvider(&data1);
1761
1762 TestCompletionCallback callback;
1763
1764 int rv = trans->Start(&request, &callback, BoundNetLog());
1765 EXPECT_EQ(ERR_IO_PENDING, rv);
1766
1767 rv = callback.WaitForResult();
1768 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1769}
1770
[email protected]2df19bb2010-08-25 20:13:461771
1772// Test a simple get through an HTTPS Proxy.
1773TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
1774 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001775 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:461776 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1777 session_deps.net_log = log.bound().net_log();
1778 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1779
[email protected]2df19bb2010-08-25 20:13:461780 HttpRequestInfo request;
1781 request.method = "GET";
1782 request.url = GURL("http://www.google.com/");
1783
1784 // Since we have proxy, should use full url
1785 MockWrite data_writes1[] = {
1786 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1787 "Host: www.google.com\r\n"
1788 "Proxy-Connection: keep-alive\r\n\r\n"),
1789 };
1790
1791 MockRead data_reads1[] = {
1792 MockRead("HTTP/1.1 200 OK\r\n"),
1793 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1794 MockRead("Content-Length: 100\r\n\r\n"),
1795 MockRead(false, OK),
1796 };
1797
1798 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1799 data_writes1, arraysize(data_writes1));
1800 session_deps.socket_factory.AddSocketDataProvider(&data1);
1801 SSLSocketDataProvider ssl(true, OK);
1802 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1803
1804 TestCompletionCallback callback1;
1805
[email protected]0b0bf032010-09-21 18:08:501806 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1807
[email protected]2df19bb2010-08-25 20:13:461808 int rv = trans->Start(&request, &callback1, log.bound());
1809 EXPECT_EQ(ERR_IO_PENDING, rv);
1810
1811 rv = callback1.WaitForResult();
1812 EXPECT_EQ(OK, rv);
1813
1814 const HttpResponseInfo* response = trans->GetResponseInfo();
1815 ASSERT_FALSE(response == NULL);
1816
1817 EXPECT_TRUE(response->headers->IsKeepAlive());
1818 EXPECT_EQ(200, response->headers->response_code());
1819 EXPECT_EQ(100, response->headers->GetContentLength());
1820 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1821
1822 // The password prompt info should not be set.
1823 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1824}
1825
[email protected]7642b5ae2010-09-01 20:55:171826// Test a SPDY get through an HTTPS Proxy.
1827TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
1828 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001829 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:171830 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1831 session_deps.net_log = log.bound().net_log();
1832 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1833
[email protected]7642b5ae2010-09-01 20:55:171834 HttpRequestInfo request;
1835 request.method = "GET";
1836 request.url = GURL("http://www.google.com/");
1837 request.load_flags = 0;
1838
1839 // fetch http://www.google.com/ via SPDY
1840 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1841 false));
1842 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1843
1844 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1845 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1846 MockRead spdy_reads[] = {
1847 CreateMockRead(*resp),
1848 CreateMockRead(*data),
1849 MockRead(true, 0, 0),
1850 };
1851
1852 scoped_refptr<DelayedSocketData> spdy_data(
1853 new DelayedSocketData(
1854 1, // wait for one write to finish before reading.
1855 spdy_reads, arraysize(spdy_reads),
1856 spdy_writes, arraysize(spdy_writes)));
1857 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1858
1859 SSLSocketDataProvider ssl(true, OK);
1860 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1861 ssl.next_proto = "spdy/2";
1862 ssl.was_npn_negotiated = true;
1863 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1864
1865 TestCompletionCallback callback1;
1866
[email protected]0b0bf032010-09-21 18:08:501867 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1868
[email protected]7642b5ae2010-09-01 20:55:171869 int rv = trans->Start(&request, &callback1, log.bound());
1870 EXPECT_EQ(ERR_IO_PENDING, rv);
1871
1872 rv = callback1.WaitForResult();
1873 EXPECT_EQ(OK, rv);
1874
1875 const HttpResponseInfo* response = trans->GetResponseInfo();
1876 ASSERT_TRUE(response != NULL);
1877 ASSERT_TRUE(response->headers != NULL);
1878 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1879
1880 std::string response_data;
1881 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1882 EXPECT_EQ(net::kUploadData, response_data);
1883}
1884
[email protected]d9da5fe2010-10-13 22:37:161885// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
1886TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
1887 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001888 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:161889 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1890 session_deps.net_log = log.bound().net_log();
1891 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1892
1893 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1894
1895 HttpRequestInfo request;
1896 request.method = "GET";
1897 request.url = GURL("https://www.google.com/");
1898 request.load_flags = 0;
1899
1900 // CONNECT to www.google.com:443 via SPDY
1901 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
1902 // fetch https://www.google.com/ via HTTP
1903
1904 const char get[] = "GET / HTTP/1.1\r\n"
1905 "Host: www.google.com\r\n"
1906 "Connection: keep-alive\r\n\r\n";
1907 scoped_ptr<spdy::SpdyFrame> wrapped_get(
1908 ConstructSpdyBodyFrame(1, get, strlen(get), false));
1909 MockWrite spdy_writes[] = {
1910 CreateMockWrite(*connect, 1),
1911 CreateMockWrite(*wrapped_get, 3)
1912 };
1913
1914 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1915 const char resp[] = "HTTP/1.1 200 OK\r\n"
1916 "Content-Length: 10\r\n\r\n";
1917
1918 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
1919 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
1920 scoped_ptr<spdy::SpdyFrame> wrapped_body(
1921 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
1922 MockRead spdy_reads[] = {
1923 CreateMockRead(*conn_resp, 2, true),
1924 CreateMockRead(*wrapped_get_resp, 4, true),
1925 CreateMockRead(*wrapped_body, 5, true),
1926 CreateMockRead(*wrapped_body, 6, true),
1927 MockRead(true, 0, 7),
1928 };
1929
1930 scoped_refptr<OrderedSocketData> spdy_data(
1931 new OrderedSocketData(
1932 spdy_reads, arraysize(spdy_reads),
1933 spdy_writes, arraysize(spdy_writes)));
1934 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1935
1936 SSLSocketDataProvider ssl(true, OK);
1937 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1938 ssl.next_proto = "spdy/2";
1939 ssl.was_npn_negotiated = true;
1940 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1941 SSLSocketDataProvider ssl2(true, OK);
1942 ssl2.was_npn_negotiated = false;
1943 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
1944
1945 TestCompletionCallback callback1;
1946
1947 int rv = trans->Start(&request, &callback1, log.bound());
1948 EXPECT_EQ(ERR_IO_PENDING, rv);
1949
1950 rv = callback1.WaitForResult();
1951 EXPECT_EQ(OK, rv);
1952
1953 const HttpResponseInfo* response = trans->GetResponseInfo();
1954 ASSERT_TRUE(response != NULL);
1955 ASSERT_TRUE(response->headers != NULL);
1956 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1957
1958 std::string response_data;
1959 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1960 EXPECT_EQ("1234567890", response_data);
1961}
1962
1963// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
1964TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
1965 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001966 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:161967 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1968 session_deps.net_log = log.bound().net_log();
1969 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1970
1971 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1972
1973 HttpRequestInfo request;
1974 request.method = "GET";
1975 request.url = GURL("https://www.google.com/");
1976 request.load_flags = 0;
1977
1978 // CONNECT to www.google.com:443 via SPDY
1979 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
1980 // fetch https://www.google.com/ via SPDY
1981 const char* const kMyUrl = "https://www.google.com/";
1982 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
1983 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
1984 MockWrite spdy_writes[] = {
1985 CreateMockWrite(*connect, 1),
1986 CreateMockWrite(*wrapped_get, 3)
1987 };
1988
1989 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1990 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1991 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
1992 ConstructWrappedSpdyFrame(get_resp, 1));
1993 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1994 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
1995 MockRead spdy_reads[] = {
1996 CreateMockRead(*conn_resp, 2, true),
1997 CreateMockRead(*wrapped_get_resp, 4, true),
1998 CreateMockRead(*wrapped_body, 5, true),
1999 MockRead(true, 0, 1),
2000 };
2001
2002 scoped_refptr<OrderedSocketData> spdy_data(
2003 new OrderedSocketData(
2004 spdy_reads, arraysize(spdy_reads),
2005 spdy_writes, arraysize(spdy_writes)));
2006 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2007
2008 SSLSocketDataProvider ssl(true, OK);
2009 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2010 ssl.next_proto = "spdy/2";
2011 ssl.was_npn_negotiated = true;
2012 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2013 SSLSocketDataProvider ssl2(true, OK);
2014 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2015 ssl2.next_proto = "spdy/2";
2016 ssl2.was_npn_negotiated = true;
2017 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2018
2019 TestCompletionCallback callback1;
2020
2021 int rv = trans->Start(&request, &callback1, log.bound());
2022 EXPECT_EQ(ERR_IO_PENDING, rv);
2023
2024 rv = callback1.WaitForResult();
2025 EXPECT_EQ(OK, rv);
2026
2027 const HttpResponseInfo* response = trans->GetResponseInfo();
2028 ASSERT_TRUE(response != NULL);
2029 ASSERT_TRUE(response->headers != NULL);
2030 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2031
2032 std::string response_data;
2033 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2034 EXPECT_EQ(net::kUploadData, response_data);
2035}
2036
2037// Test a SPDY CONNECT failure through an HTTPS Proxy.
2038TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
2039 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002040 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162041 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2042 session_deps.net_log = log.bound().net_log();
2043 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2044
2045 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2046
2047 HttpRequestInfo request;
2048 request.method = "GET";
2049 request.url = GURL("https://www.google.com/");
2050 request.load_flags = 0;
2051
2052 // CONNECT to www.google.com:443 via SPDY
2053 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2054 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2055
2056 MockWrite spdy_writes[] = {
2057 CreateMockWrite(*connect, 1),
2058 CreateMockWrite(*get, 3),
2059 };
2060
2061 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2062 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2063 MockRead spdy_reads[] = {
2064 CreateMockRead(*resp, 2, true),
2065 MockRead(true, 0, 4),
2066 };
2067
2068 scoped_refptr<OrderedSocketData> spdy_data(
2069 new OrderedSocketData(
2070 spdy_reads, arraysize(spdy_reads),
2071 spdy_writes, arraysize(spdy_writes)));
2072 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2073
2074 SSLSocketDataProvider ssl(true, OK);
2075 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2076 ssl.next_proto = "spdy/2";
2077 ssl.was_npn_negotiated = true;
2078 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2079 SSLSocketDataProvider ssl2(true, OK);
2080 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2081 ssl2.next_proto = "spdy/2";
2082 ssl2.was_npn_negotiated = true;
2083 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2084
2085 TestCompletionCallback callback1;
2086
2087 int rv = trans->Start(&request, &callback1, log.bound());
2088 EXPECT_EQ(ERR_IO_PENDING, rv);
2089
2090 rv = callback1.WaitForResult();
2091 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2092
2093 const HttpResponseInfo* response = trans->GetResponseInfo();
2094 ASSERT_TRUE(response == NULL);
2095}
2096
[email protected]2df19bb2010-08-25 20:13:462097// Test the challenge-response-retry sequence through an HTTPS Proxy
2098TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
2099 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002100 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:462101 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2102 session_deps.net_log = log.bound().net_log();
2103 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2104
[email protected]2df19bb2010-08-25 20:13:462105 HttpRequestInfo request;
2106 request.method = "GET";
2107 request.url = GURL("http://www.google.com/");
2108 // when the no authentication data flag is set.
2109 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2110
2111 // Since we have proxy, should use full url
2112 MockWrite data_writes1[] = {
2113 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2114 "Host: www.google.com\r\n"
2115 "Proxy-Connection: keep-alive\r\n\r\n"),
2116
2117 // After calling trans->RestartWithAuth(), this is the request we should
2118 // be issuing -- the final header line contains the credentials.
2119 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2120 "Host: www.google.com\r\n"
2121 "Proxy-Connection: keep-alive\r\n"
2122 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2123 };
2124
2125 // The proxy responds to the GET with a 407, using a persistent
2126 // connection.
2127 MockRead data_reads1[] = {
2128 // No credentials.
2129 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2130 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2131 MockRead("Proxy-Connection: keep-alive\r\n"),
2132 MockRead("Content-Length: 0\r\n\r\n"),
2133
2134 MockRead("HTTP/1.1 200 OK\r\n"),
2135 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2136 MockRead("Content-Length: 100\r\n\r\n"),
2137 MockRead(false, OK),
2138 };
2139
2140 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2141 data_writes1, arraysize(data_writes1));
2142 session_deps.socket_factory.AddSocketDataProvider(&data1);
2143 SSLSocketDataProvider ssl(true, OK);
2144 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2145
2146 TestCompletionCallback callback1;
2147
[email protected]0b0bf032010-09-21 18:08:502148 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2149
[email protected]2df19bb2010-08-25 20:13:462150 int rv = trans->Start(&request, &callback1, log.bound());
2151 EXPECT_EQ(ERR_IO_PENDING, rv);
2152
2153 rv = callback1.WaitForResult();
2154 EXPECT_EQ(OK, rv);
2155
2156 const HttpResponseInfo* response = trans->GetResponseInfo();
2157 ASSERT_FALSE(response == NULL);
2158
2159 EXPECT_EQ(407, response->headers->response_code());
2160 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2161
2162 // The password prompt info should have been set in response->auth_challenge.
2163 ASSERT_FALSE(response->auth_challenge.get() == NULL);
2164
2165 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2166 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2167 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2168
2169 TestCompletionCallback callback2;
2170
2171 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2172 EXPECT_EQ(ERR_IO_PENDING, rv);
2173
2174 rv = callback2.WaitForResult();
2175 EXPECT_EQ(OK, rv);
2176
2177 response = trans->GetResponseInfo();
2178 ASSERT_FALSE(response == NULL);
2179
2180 EXPECT_TRUE(response->headers->IsKeepAlive());
2181 EXPECT_EQ(200, response->headers->response_code());
2182 EXPECT_EQ(100, response->headers->GetContentLength());
2183 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2184
2185 // The password prompt info should not be set.
2186 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2187}
2188
[email protected]ff007e162009-05-23 09:13:152189void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082190 const MockRead& status, int expected_status) {
2191 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:002192 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:082193
[email protected]228ff742009-06-05 01:19:592194 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:082195
[email protected]1c773ea12009-04-28 19:58:422196 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082197 request.method = "GET";
2198 request.url = GURL("https://www.google.com/");
2199 request.load_flags = 0;
2200
2201 // Since we have proxy, should try to establish tunnel.
2202 MockWrite data_writes[] = {
2203 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452204 "Host: www.google.com\r\n"
2205 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082206 };
2207
2208 MockRead data_reads[] = {
2209 status,
2210 MockRead("Content-Length: 10\r\n\r\n"),
2211 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422212 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082213 };
2214
[email protected]31a2bfe2010-02-09 08:03:392215 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2216 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592217 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082218
2219 TestCompletionCallback callback;
2220
[email protected]0b0bf032010-09-21 18:08:502221 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2222
[email protected]5a1d7ca2010-04-28 20:12:272223 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422224 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082225
2226 rv = callback.WaitForResult();
2227 EXPECT_EQ(expected_status, rv);
2228}
2229
[email protected]ff007e162009-05-23 09:13:152230void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082231 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422232 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082233}
2234
2235TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2236 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2237}
2238
2239TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2240 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2241}
2242
2243TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2244 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2245}
2246
2247TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2248 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2249}
2250
2251TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2252 ConnectStatusHelper(
2253 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2254}
2255
2256TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2257 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2258}
2259
2260TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2261 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2262}
2263
2264TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2265 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2266}
2267
2268TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2269 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2270}
2271
2272TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2273 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2274}
2275
2276TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2277 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2278}
2279
2280TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2281 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2282}
2283
2284TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2285 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2286}
2287
2288TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2289 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2290}
2291
2292TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2293 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2294}
2295
2296TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2297 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2298}
2299
2300TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2301 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2302}
2303
2304TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2305 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2306}
2307
2308TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2309 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2310}
2311
2312TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2313 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2314}
2315
2316TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2317 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2318}
2319
2320TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2321 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2322}
2323
2324TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2325 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2326}
2327
2328TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2329 ConnectStatusHelperWithExpectedStatus(
2330 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542331 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082332}
2333
2334TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2335 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2336}
2337
2338TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2339 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2340}
2341
2342TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2343 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2344}
2345
2346TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2347 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2348}
2349
2350TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2351 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2352}
2353
2354TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2355 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2356}
2357
2358TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2359 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2360}
2361
2362TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2363 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2364}
2365
2366TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2367 ConnectStatusHelper(
2368 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2369}
2370
2371TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2372 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2373}
2374
2375TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2376 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2377}
2378
2379TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2380 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2381}
2382
2383TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2384 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2385}
2386
2387TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2388 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2389}
2390
2391TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2392 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2393}
2394
2395TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2396 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2397}
2398
[email protected]038e9a32008-10-08 22:40:162399// Test the flow when both the proxy server AND origin server require
2400// authentication. Again, this uses basic auth for both since that is
2401// the simplest to mock.
2402TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]81cdfcd2010-10-16 00:49:002403 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012404
[email protected]038e9a32008-10-08 22:40:162405 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422406 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432407 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162408
[email protected]1c773ea12009-04-28 19:58:422409 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162410 request.method = "GET";
2411 request.url = GURL("http://www.google.com/");
2412 request.load_flags = 0;
2413
[email protected]f9ee6b52008-11-08 06:46:232414 MockWrite data_writes1[] = {
2415 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2416 "Host: www.google.com\r\n"
2417 "Proxy-Connection: keep-alive\r\n\r\n"),
2418 };
2419
[email protected]038e9a32008-10-08 22:40:162420 MockRead data_reads1[] = {
2421 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2422 // Give a couple authenticate options (only the middle one is actually
2423 // supported).
[email protected]22927ad2009-09-21 19:56:192424 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162425 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2426 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2427 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2428 // Large content-length -- won't matter, as connection will be reset.
2429 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422430 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162431 };
2432
2433 // After calling trans->RestartWithAuth() the first time, this is the
2434 // request we should be issuing -- the final header line contains the
2435 // proxy's credentials.
2436 MockWrite data_writes2[] = {
2437 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2438 "Host: www.google.com\r\n"
2439 "Proxy-Connection: keep-alive\r\n"
2440 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2441 };
2442
2443 // Now the proxy server lets the request pass through to origin server.
2444 // The origin server responds with a 401.
2445 MockRead data_reads2[] = {
2446 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2447 // Note: We are using the same realm-name as the proxy server. This is
2448 // completely valid, as realms are unique across hosts.
2449 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2450 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2451 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422452 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162453 };
2454
2455 // After calling trans->RestartWithAuth() the second time, we should send
2456 // the credentials for both the proxy and origin server.
2457 MockWrite data_writes3[] = {
2458 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2459 "Host: www.google.com\r\n"
2460 "Proxy-Connection: keep-alive\r\n"
2461 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2462 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2463 };
2464
2465 // Lastly we get the desired content.
2466 MockRead data_reads3[] = {
2467 MockRead("HTTP/1.0 200 OK\r\n"),
2468 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2469 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422470 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162471 };
2472
[email protected]31a2bfe2010-02-09 08:03:392473 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2474 data_writes1, arraysize(data_writes1));
2475 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2476 data_writes2, arraysize(data_writes2));
2477 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2478 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592479 session_deps.socket_factory.AddSocketDataProvider(&data1);
2480 session_deps.socket_factory.AddSocketDataProvider(&data2);
2481 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162482
2483 TestCompletionCallback callback1;
2484
[email protected]5a1d7ca2010-04-28 20:12:272485 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422486 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162487
2488 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422489 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162490
[email protected]1c773ea12009-04-28 19:58:422491 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162492 EXPECT_FALSE(response == NULL);
2493
2494 // The password prompt info should have been set in response->auth_challenge.
2495 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2496
[email protected]71e4573a2009-05-21 22:03:002497 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162498 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2499 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2500
2501 TestCompletionCallback callback2;
2502
[email protected]13c8a092010-07-29 06:15:442503 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422504 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162505
2506 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422507 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162508
2509 response = trans->GetResponseInfo();
2510 EXPECT_FALSE(response == NULL);
2511 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2512
[email protected]71e4573a2009-05-21 22:03:002513 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162514 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2515 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2516
2517 TestCompletionCallback callback3;
2518
[email protected]13c8a092010-07-29 06:15:442519 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422520 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162521
2522 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422523 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162524
2525 response = trans->GetResponseInfo();
2526 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2527 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162528}
[email protected]4ddaf2502008-10-23 18:26:192529
[email protected]ea9dc9a2009-09-05 00:43:322530// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2531// can't hook into its internals to cause it to generate predictable NTLM
2532// authorization headers.
2533#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292534// The NTLM authentication unit tests were generated by capturing the HTTP
2535// requests and responses using Fiddler 2 and inspecting the generated random
2536// bytes in the debugger.
2537
2538// Enter the correct password and authenticate successfully.
2539TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422540 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:112541 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592542 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502543 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3f918782009-02-28 01:29:242544
[email protected]1c773ea12009-04-28 19:58:422545 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242546 request.method = "GET";
2547 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2548 request.load_flags = 0;
2549
2550 MockWrite data_writes1[] = {
2551 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2552 "Host: 172.22.68.17\r\n"
2553 "Connection: keep-alive\r\n\r\n"),
2554 };
2555
2556 MockRead data_reads1[] = {
2557 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042558 // Negotiate and NTLM are often requested together. However, we only want
2559 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2560 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242561 MockRead("WWW-Authenticate: NTLM\r\n"),
2562 MockRead("Connection: close\r\n"),
2563 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362564 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242565 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422566 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242567 };
2568
2569 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222570 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242571 // request we should be issuing -- the final header line contains a Type
2572 // 1 message.
2573 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2574 "Host: 172.22.68.17\r\n"
2575 "Connection: keep-alive\r\n"
2576 "Authorization: NTLM "
2577 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2578
2579 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2580 // (the credentials for the origin server). The second request continues
2581 // on the same connection.
2582 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2583 "Host: 172.22.68.17\r\n"
2584 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292585 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2586 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2587 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2588 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2589 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242590 };
2591
2592 MockRead data_reads2[] = {
2593 // The origin server responds with a Type 2 message.
2594 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2595 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292596 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242597 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2598 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2599 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2600 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2601 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2602 "BtAAAAAAA=\r\n"),
2603 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362604 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242605 MockRead("You are not authorized to view this page\r\n"),
2606
2607 // Lastly we get the desired content.
2608 MockRead("HTTP/1.1 200 OK\r\n"),
2609 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2610 MockRead("Content-Length: 13\r\n\r\n"),
2611 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422612 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242613 };
2614
[email protected]31a2bfe2010-02-09 08:03:392615 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2616 data_writes1, arraysize(data_writes1));
2617 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2618 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592619 session_deps.socket_factory.AddSocketDataProvider(&data1);
2620 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242621
2622 TestCompletionCallback callback1;
2623
[email protected]0b0bf032010-09-21 18:08:502624 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2625
[email protected]5a1d7ca2010-04-28 20:12:272626 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422627 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242628
2629 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422630 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242631
[email protected]0757e7702009-03-27 04:00:222632 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2633 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442634 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422635 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222636 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422637 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222638 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2639
[email protected]1c773ea12009-04-28 19:58:422640 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042641 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242642
[email protected]aef04272010-06-28 18:03:042643 // The password prompt info should have been set in
2644 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242645 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2646
[email protected]71e4573a2009-05-21 22:03:002647 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242648 EXPECT_EQ(L"", response->auth_challenge->realm);
2649 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2650
[email protected]0757e7702009-03-27 04:00:222651 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242652
[email protected]13c8a092010-07-29 06:15:442653 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422654 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242655
[email protected]0757e7702009-03-27 04:00:222656 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422657 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242658
2659 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042660 ASSERT_FALSE(response == NULL);
2661
[email protected]3f918782009-02-28 01:29:242662 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2663 EXPECT_EQ(13, response->headers->GetContentLength());
2664}
2665
[email protected]385a4672009-03-11 22:21:292666// Enter a wrong password, and then the correct one.
2667TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422668 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112669 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592670 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502671 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]385a4672009-03-11 22:21:292672
[email protected]1c773ea12009-04-28 19:58:422673 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292674 request.method = "GET";
2675 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2676 request.load_flags = 0;
2677
2678 MockWrite data_writes1[] = {
2679 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2680 "Host: 172.22.68.17\r\n"
2681 "Connection: keep-alive\r\n\r\n"),
2682 };
2683
2684 MockRead data_reads1[] = {
2685 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042686 // Negotiate and NTLM are often requested together. However, we only want
2687 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2688 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292689 MockRead("WWW-Authenticate: NTLM\r\n"),
2690 MockRead("Connection: close\r\n"),
2691 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362692 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292693 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422694 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292695 };
2696
2697 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222698 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292699 // request we should be issuing -- the final header line contains a Type
2700 // 1 message.
2701 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2702 "Host: 172.22.68.17\r\n"
2703 "Connection: keep-alive\r\n"
2704 "Authorization: NTLM "
2705 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2706
2707 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2708 // (the credentials for the origin server). The second request continues
2709 // on the same connection.
2710 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2711 "Host: 172.22.68.17\r\n"
2712 "Connection: keep-alive\r\n"
2713 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2714 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2715 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2716 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2717 "4Ww7b7E=\r\n\r\n"),
2718 };
2719
2720 MockRead data_reads2[] = {
2721 // The origin server responds with a Type 2 message.
2722 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2723 MockRead("WWW-Authenticate: NTLM "
2724 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2725 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2726 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2727 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2728 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2729 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2730 "BtAAAAAAA=\r\n"),
2731 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362732 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292733 MockRead("You are not authorized to view this page\r\n"),
2734
2735 // Wrong password.
2736 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292737 MockRead("WWW-Authenticate: NTLM\r\n"),
2738 MockRead("Connection: close\r\n"),
2739 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362740 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292741 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422742 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292743 };
2744
2745 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222746 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292747 // request we should be issuing -- the final header line contains a Type
2748 // 1 message.
2749 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2750 "Host: 172.22.68.17\r\n"
2751 "Connection: keep-alive\r\n"
2752 "Authorization: NTLM "
2753 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2754
2755 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2756 // (the credentials for the origin server). The second request continues
2757 // on the same connection.
2758 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2759 "Host: 172.22.68.17\r\n"
2760 "Connection: keep-alive\r\n"
2761 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2762 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2763 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2764 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2765 "+4MUm7c=\r\n\r\n"),
2766 };
2767
2768 MockRead data_reads3[] = {
2769 // The origin server responds with a Type 2 message.
2770 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2771 MockRead("WWW-Authenticate: NTLM "
2772 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2773 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2774 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2775 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2776 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2777 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2778 "BtAAAAAAA=\r\n"),
2779 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362780 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292781 MockRead("You are not authorized to view this page\r\n"),
2782
2783 // Lastly we get the desired content.
2784 MockRead("HTTP/1.1 200 OK\r\n"),
2785 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2786 MockRead("Content-Length: 13\r\n\r\n"),
2787 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422788 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292789 };
2790
[email protected]31a2bfe2010-02-09 08:03:392791 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2792 data_writes1, arraysize(data_writes1));
2793 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2794 data_writes2, arraysize(data_writes2));
2795 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2796 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592797 session_deps.socket_factory.AddSocketDataProvider(&data1);
2798 session_deps.socket_factory.AddSocketDataProvider(&data2);
2799 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292800
2801 TestCompletionCallback callback1;
2802
[email protected]0b0bf032010-09-21 18:08:502803 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2804
[email protected]5a1d7ca2010-04-28 20:12:272805 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422806 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292807
2808 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422809 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292810
[email protected]0757e7702009-03-27 04:00:222811 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292812 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442813 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422814 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292815 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422816 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222817 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292818
[email protected]1c773ea12009-04-28 19:58:422819 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292820 EXPECT_FALSE(response == NULL);
2821
2822 // The password prompt info should have been set in response->auth_challenge.
2823 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2824
[email protected]71e4573a2009-05-21 22:03:002825 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292826 EXPECT_EQ(L"", response->auth_challenge->realm);
2827 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2828
2829 TestCompletionCallback callback3;
2830
[email protected]0757e7702009-03-27 04:00:222831 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:442832 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:422833 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292834
2835 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422836 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292837
[email protected]0757e7702009-03-27 04:00:222838 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2839 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:442840 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422841 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222842 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422843 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222844 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2845
2846 response = trans->GetResponseInfo();
2847 EXPECT_FALSE(response == NULL);
2848
2849 // The password prompt info should have been set in response->auth_challenge.
2850 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2851
[email protected]71e4573a2009-05-21 22:03:002852 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222853 EXPECT_EQ(L"", response->auth_challenge->realm);
2854 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2855
2856 TestCompletionCallback callback5;
2857
2858 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:442859 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:422860 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222861
2862 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422863 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222864
[email protected]385a4672009-03-11 22:21:292865 response = trans->GetResponseInfo();
2866 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2867 EXPECT_EQ(13, response->headers->GetContentLength());
2868}
[email protected]ea9dc9a2009-09-05 00:43:322869#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292870
[email protected]4ddaf2502008-10-23 18:26:192871// Test reading a server response which has only headers, and no body.
2872// After some maximum number of bytes is consumed, the transaction should
2873// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2874TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592875 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402876 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432877 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192878
[email protected]1c773ea12009-04-28 19:58:422879 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192880 request.method = "GET";
2881 request.url = GURL("http://www.google.com/");
2882 request.load_flags = 0;
2883
[email protected]b75b7b2f2009-10-06 00:54:532884 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432885 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532886 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192887
2888 MockRead data_reads[] = {
2889 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432890 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192891 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422892 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192893 };
[email protected]31a2bfe2010-02-09 08:03:392894 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592895 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192896
2897 TestCompletionCallback callback;
2898
[email protected]5a1d7ca2010-04-28 20:12:272899 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422900 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192901
2902 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422903 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192904
[email protected]1c773ea12009-04-28 19:58:422905 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192906 EXPECT_TRUE(response == NULL);
2907}
[email protected]f4e426b2008-11-05 00:24:492908
2909// Make sure that we don't try to reuse a TCPClientSocket when failing to
2910// establish tunnel.
2911// http://code.google.com/p/chromium/issues/detail?id=3772
2912TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2913 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:002914 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012915
[email protected]228ff742009-06-05 01:19:592916 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492917
[email protected]5695b8c2009-09-30 21:36:432918 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492919
[email protected]1c773ea12009-04-28 19:58:422920 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492921 request.method = "GET";
2922 request.url = GURL("https://www.google.com/");
2923 request.load_flags = 0;
2924
2925 // Since we have proxy, should try to establish tunnel.
2926 MockWrite data_writes1[] = {
2927 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452928 "Host: www.google.com\r\n"
2929 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492930 };
2931
[email protected]77848d12008-11-14 00:00:222932 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492933 // connection. Usually a proxy would return 501 (not implemented),
2934 // or 200 (tunnel established).
2935 MockRead data_reads1[] = {
2936 MockRead("HTTP/1.1 404 Not Found\r\n"),
2937 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422938 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492939 };
2940
[email protected]31a2bfe2010-02-09 08:03:392941 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2942 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592943 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492944
2945 TestCompletionCallback callback1;
2946
[email protected]5a1d7ca2010-04-28 20:12:272947 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422948 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492949
2950 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422951 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492952
[email protected]1c773ea12009-04-28 19:58:422953 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082954 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492955
[email protected]b4404c02009-04-10 16:38:522956 // Empty the current queue. This is necessary because idle sockets are
2957 // added to the connection pool asynchronously with a PostTask.
2958 MessageLoop::current()->RunAllPending();
2959
[email protected]f4e426b2008-11-05 00:24:492960 // We now check to make sure the TCPClientSocket was not added back to
2961 // the pool.
[email protected]a937a06d2009-08-19 21:19:242962 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492963 trans.reset();
[email protected]b4404c02009-04-10 16:38:522964 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492965 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242966 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492967}
[email protected]372d34a2008-11-05 21:30:512968
[email protected]1b157c02009-04-21 01:55:402969// Make sure that we recycle a socket after reading all of the response body.
2970TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592971 SessionDependencies session_deps;
2972 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402973
[email protected]5695b8c2009-09-30 21:36:432974 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402975
[email protected]1c773ea12009-04-28 19:58:422976 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402977 request.method = "GET";
2978 request.url = GURL("http://www.google.com/");
2979 request.load_flags = 0;
2980
2981 MockRead data_reads[] = {
2982 // A part of the response body is received with the response headers.
2983 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2984 // The rest of the response body is received in two parts.
2985 MockRead("lo"),
2986 MockRead(" world"),
2987 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422988 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402989 };
2990
[email protected]31a2bfe2010-02-09 08:03:392991 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592992 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402993
2994 TestCompletionCallback callback;
2995
[email protected]5a1d7ca2010-04-28 20:12:272996 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422997 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402998
2999 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423000 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403001
[email protected]1c773ea12009-04-28 19:58:423002 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:403003 EXPECT_TRUE(response != NULL);
3004
3005 EXPECT_TRUE(response->headers != NULL);
3006 std::string status_line = response->headers->GetStatusLine();
3007 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3008
[email protected]a937a06d2009-08-19 21:19:243009 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403010
3011 std::string response_data;
3012 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423013 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403014 EXPECT_EQ("hello world", response_data);
3015
3016 // Empty the current queue. This is necessary because idle sockets are
3017 // added to the connection pool asynchronously with a PostTask.
3018 MessageLoop::current()->RunAllPending();
3019
3020 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243021 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403022}
3023
[email protected]76a505b2010-08-25 06:23:003024// Make sure that we recycle a SSL socket after reading all of the response
3025// body.
3026TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3027 SessionDependencies session_deps;
3028 HttpRequestInfo request;
3029 request.method = "GET";
3030 request.url = GURL("https://www.google.com/");
3031 request.load_flags = 0;
3032
3033 MockWrite data_writes[] = {
3034 MockWrite("GET / HTTP/1.1\r\n"
3035 "Host: www.google.com\r\n"
3036 "Connection: keep-alive\r\n\r\n"),
3037 };
3038
3039 MockRead data_reads[] = {
3040 MockRead("HTTP/1.1 200 OK\r\n"),
3041 MockRead("Content-Length: 11\r\n\r\n"),
3042 MockRead("hello world"),
3043 MockRead(false, OK),
3044 };
3045
3046 SSLSocketDataProvider ssl(true, OK);
3047 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3048
3049 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3050 data_writes, arraysize(data_writes));
3051 session_deps.socket_factory.AddSocketDataProvider(&data);
3052
3053 TestCompletionCallback callback;
3054
3055 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3056 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3057
3058 int rv = trans->Start(&request, &callback, BoundNetLog());
3059
3060 EXPECT_EQ(ERR_IO_PENDING, rv);
3061 EXPECT_EQ(OK, callback.WaitForResult());
3062
3063 const HttpResponseInfo* response = trans->GetResponseInfo();
3064 ASSERT_TRUE(response != NULL);
3065 ASSERT_TRUE(response->headers != NULL);
3066 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3067
3068 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3069
3070 std::string response_data;
3071 rv = ReadTransaction(trans.get(), &response_data);
3072 EXPECT_EQ(OK, rv);
3073 EXPECT_EQ("hello world", response_data);
3074
3075 // Empty the current queue. This is necessary because idle sockets are
3076 // added to the connection pool asynchronously with a PostTask.
3077 MessageLoop::current()->RunAllPending();
3078
3079 // We now check to make sure the socket was added back to the pool.
3080 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3081}
3082
3083// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3084// from the pool and make sure that we recover okay.
3085TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3086 SessionDependencies session_deps;
3087 HttpRequestInfo request;
3088 request.method = "GET";
3089 request.url = GURL("https://www.google.com/");
3090 request.load_flags = 0;
3091
3092 MockWrite data_writes[] = {
3093 MockWrite("GET / HTTP/1.1\r\n"
3094 "Host: www.google.com\r\n"
3095 "Connection: keep-alive\r\n\r\n"),
3096 MockWrite("GET / HTTP/1.1\r\n"
3097 "Host: www.google.com\r\n"
3098 "Connection: keep-alive\r\n\r\n"),
3099 };
3100
3101 MockRead data_reads[] = {
3102 MockRead("HTTP/1.1 200 OK\r\n"),
3103 MockRead("Content-Length: 11\r\n\r\n"),
3104 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3105 MockRead("hello world"),
3106 MockRead(true, 0, 0) // EOF
3107 };
3108
3109 SSLSocketDataProvider ssl(true, OK);
3110 SSLSocketDataProvider ssl2(true, OK);
3111 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3112 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3113
3114 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3115 data_writes, arraysize(data_writes));
3116 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3117 data_writes, arraysize(data_writes));
3118 session_deps.socket_factory.AddSocketDataProvider(&data);
3119 session_deps.socket_factory.AddSocketDataProvider(&data2);
3120
3121 TestCompletionCallback callback;
3122
3123 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3124 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3125
3126 int rv = trans->Start(&request, &callback, BoundNetLog());
3127
3128 EXPECT_EQ(ERR_IO_PENDING, rv);
3129 EXPECT_EQ(OK, callback.WaitForResult());
3130
3131 const HttpResponseInfo* response = trans->GetResponseInfo();
3132 ASSERT_TRUE(response != NULL);
3133 ASSERT_TRUE(response->headers != NULL);
3134 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3135
3136 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3137
3138 std::string response_data;
3139 rv = ReadTransaction(trans.get(), &response_data);
3140 EXPECT_EQ(OK, rv);
3141 EXPECT_EQ("hello world", response_data);
3142
3143 // Empty the current queue. This is necessary because idle sockets are
3144 // added to the connection pool asynchronously with a PostTask.
3145 MessageLoop::current()->RunAllPending();
3146
3147 // We now check to make sure the socket was added back to the pool.
3148 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3149
3150 // Now start the second transaction, which should reuse the previous socket.
3151
3152 trans.reset(new HttpNetworkTransaction(session));
3153
3154 rv = trans->Start(&request, &callback, BoundNetLog());
3155
3156 EXPECT_EQ(ERR_IO_PENDING, rv);
3157 EXPECT_EQ(OK, callback.WaitForResult());
3158
3159 response = trans->GetResponseInfo();
3160 ASSERT_TRUE(response != NULL);
3161 ASSERT_TRUE(response->headers != NULL);
3162 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3163
3164 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3165
3166 rv = ReadTransaction(trans.get(), &response_data);
3167 EXPECT_EQ(OK, rv);
3168 EXPECT_EQ("hello world", response_data);
3169
3170 // Empty the current queue. This is necessary because idle sockets are
3171 // added to the connection pool asynchronously with a PostTask.
3172 MessageLoop::current()->RunAllPending();
3173
3174 // We now check to make sure the socket was added back to the pool.
3175 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3176}
3177
[email protected]b4404c02009-04-10 16:38:523178// Make sure that we recycle a socket after a zero-length response.
3179// http://crbug.com/9880
3180TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:593181 SessionDependencies session_deps;
3182 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:523183
[email protected]5695b8c2009-09-30 21:36:433184 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:523185
[email protected]1c773ea12009-04-28 19:58:423186 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523187 request.method = "GET";
3188 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3189 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3190 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3191 "rt=prt.2642,ol.2649,xjs.2951");
3192 request.load_flags = 0;
3193
3194 MockRead data_reads[] = {
3195 MockRead("HTTP/1.1 204 No Content\r\n"
3196 "Content-Length: 0\r\n"
3197 "Content-Type: text/html\r\n\r\n"),
3198 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423199 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523200 };
3201
[email protected]31a2bfe2010-02-09 08:03:393202 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593203 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523204
3205 TestCompletionCallback callback;
3206
[email protected]5a1d7ca2010-04-28 20:12:273207 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423208 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523209
3210 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423211 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523212
[email protected]1c773ea12009-04-28 19:58:423213 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523214 EXPECT_TRUE(response != NULL);
3215
3216 EXPECT_TRUE(response->headers != NULL);
3217 std::string status_line = response->headers->GetStatusLine();
3218 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3219
[email protected]a937a06d2009-08-19 21:19:243220 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523221
3222 std::string response_data;
3223 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423224 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523225 EXPECT_EQ("", response_data);
3226
3227 // Empty the current queue. This is necessary because idle sockets are
3228 // added to the connection pool asynchronously with a PostTask.
3229 MessageLoop::current()->RunAllPending();
3230
3231 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243232 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523233}
3234
[email protected]372d34a2008-11-05 21:30:513235TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423236 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513237 // Transaction 1: a GET request that succeeds. The socket is recycled
3238 // after use.
3239 request[0].method = "GET";
3240 request[0].url = GURL("http://www.google.com/");
3241 request[0].load_flags = 0;
3242 // Transaction 2: a POST request. Reuses the socket kept alive from
3243 // transaction 1. The first attempts fails when writing the POST data.
3244 // This causes the transaction to retry with a new socket. The second
3245 // attempt succeeds.
3246 request[1].method = "POST";
3247 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423248 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513249 request[1].upload_data->AppendBytes("foo", 3);
3250 request[1].load_flags = 0;
3251
[email protected]228ff742009-06-05 01:19:593252 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273253 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513254
3255 // The first socket is used for transaction 1 and the first attempt of
3256 // transaction 2.
3257
3258 // The response of transaction 1.
3259 MockRead data_reads1[] = {
3260 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3261 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423262 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513263 };
3264 // The mock write results of transaction 1 and the first attempt of
3265 // transaction 2.
3266 MockWrite data_writes1[] = {
3267 MockWrite(false, 64), // GET
3268 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423269 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513270 };
[email protected]31a2bfe2010-02-09 08:03:393271 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3272 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513273
3274 // The second socket is used for the second attempt of transaction 2.
3275
3276 // The response of transaction 2.
3277 MockRead data_reads2[] = {
3278 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3279 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423280 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513281 };
3282 // The mock write results of the second attempt of transaction 2.
3283 MockWrite data_writes2[] = {
3284 MockWrite(false, 93), // POST
3285 MockWrite(false, 3), // POST data
3286 };
[email protected]31a2bfe2010-02-09 08:03:393287 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3288 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513289
[email protected]5ecc992a42009-11-11 01:41:593290 session_deps.socket_factory.AddSocketDataProvider(&data1);
3291 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513292
3293 const char* kExpectedResponseData[] = {
3294 "hello world", "welcome"
3295 };
3296
3297 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423298 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433299 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513300
3301 TestCompletionCallback callback;
3302
[email protected]5a1d7ca2010-04-28 20:12:273303 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423304 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513305
3306 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423307 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513308
[email protected]1c773ea12009-04-28 19:58:423309 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513310 EXPECT_TRUE(response != NULL);
3311
3312 EXPECT_TRUE(response->headers != NULL);
3313 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3314
3315 std::string response_data;
3316 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423317 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513318 EXPECT_EQ(kExpectedResponseData[i], response_data);
3319 }
3320}
[email protected]f9ee6b52008-11-08 06:46:233321
3322// Test the request-challenge-retry sequence for basic auth when there is
3323// an identity in the URL. The request should be sent as normal, but when
3324// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323325TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:593326 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403327 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433328 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:233329
[email protected]1c773ea12009-04-28 19:58:423330 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233331 request.method = "GET";
3332 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293333 request.url = GURL("http://foo:b@[email protected]/");
3334
3335 // The password contains an escaped character -- for this test to pass it
3336 // will need to be unescaped by HttpNetworkTransaction.
3337 EXPECT_EQ("b%40r", request.url.password());
3338
[email protected]ea9dc9a2009-09-05 00:43:323339 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233340
3341 MockWrite data_writes1[] = {
3342 MockWrite("GET / HTTP/1.1\r\n"
3343 "Host: www.google.com\r\n"
3344 "Connection: keep-alive\r\n\r\n"),
3345 };
3346
3347 MockRead data_reads1[] = {
3348 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3349 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3350 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423351 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233352 };
3353
3354 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323355 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233356 MockWrite data_writes2[] = {
3357 MockWrite("GET / HTTP/1.1\r\n"
3358 "Host: www.google.com\r\n"
3359 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293360 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233361 };
3362
3363 MockRead data_reads2[] = {
3364 MockRead("HTTP/1.0 200 OK\r\n"),
3365 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423366 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233367 };
3368
[email protected]31a2bfe2010-02-09 08:03:393369 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3370 data_writes1, arraysize(data_writes1));
3371 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3372 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593373 session_deps.socket_factory.AddSocketDataProvider(&data1);
3374 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233375
3376 TestCompletionCallback callback1;
3377
[email protected]5a1d7ca2010-04-28 20:12:273378 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423379 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233380
3381 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423382 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233383
[email protected]0757e7702009-03-27 04:00:223384 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3385 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443386 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423387 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223388 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423389 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223390 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3391
[email protected]1c773ea12009-04-28 19:58:423392 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233393 EXPECT_FALSE(response == NULL);
3394
3395 // There is no challenge info, since the identity in URL worked.
3396 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3397
3398 EXPECT_EQ(100, response->headers->GetContentLength());
3399
3400 // Empty the current queue.
3401 MessageLoop::current()->RunAllPending();
3402}
3403
[email protected]ea9dc9a2009-09-05 00:43:323404// Test the request-challenge-retry sequence for basic auth when there is
3405// an incorrect identity in the URL. The identity from the URL should be used
3406// only once.
3407TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
3408 SessionDependencies session_deps;
3409 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433410 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:323411
3412 HttpRequestInfo request;
3413 request.method = "GET";
3414 // Note: the URL has a username:password in it. The password "baz" is
3415 // wrong (should be "bar").
3416 request.url = GURL("http://foo:[email protected]/");
3417
3418 request.load_flags = LOAD_NORMAL;
3419
3420 MockWrite data_writes1[] = {
3421 MockWrite("GET / HTTP/1.1\r\n"
3422 "Host: www.google.com\r\n"
3423 "Connection: keep-alive\r\n\r\n"),
3424 };
3425
3426 MockRead data_reads1[] = {
3427 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3428 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3429 MockRead("Content-Length: 10\r\n\r\n"),
3430 MockRead(false, ERR_FAILED),
3431 };
3432
3433 // After the challenge above, the transaction will be restarted using the
3434 // identity from the url (foo, baz) to answer the challenge.
3435 MockWrite data_writes2[] = {
3436 MockWrite("GET / HTTP/1.1\r\n"
3437 "Host: www.google.com\r\n"
3438 "Connection: keep-alive\r\n"
3439 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3440 };
3441
3442 MockRead data_reads2[] = {
3443 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3444 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3445 MockRead("Content-Length: 10\r\n\r\n"),
3446 MockRead(false, ERR_FAILED),
3447 };
3448
3449 // After the challenge above, the transaction will be restarted using the
3450 // identity supplied by the user (foo, bar) to answer the challenge.
3451 MockWrite data_writes3[] = {
3452 MockWrite("GET / HTTP/1.1\r\n"
3453 "Host: www.google.com\r\n"
3454 "Connection: keep-alive\r\n"
3455 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3456 };
3457
3458 MockRead data_reads3[] = {
3459 MockRead("HTTP/1.0 200 OK\r\n"),
3460 MockRead("Content-Length: 100\r\n\r\n"),
3461 MockRead(false, OK),
3462 };
3463
[email protected]31a2bfe2010-02-09 08:03:393464 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3465 data_writes1, arraysize(data_writes1));
3466 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3467 data_writes2, arraysize(data_writes2));
3468 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3469 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593470 session_deps.socket_factory.AddSocketDataProvider(&data1);
3471 session_deps.socket_factory.AddSocketDataProvider(&data2);
3472 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323473
3474 TestCompletionCallback callback1;
3475
[email protected]5a1d7ca2010-04-28 20:12:273476 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323477 EXPECT_EQ(ERR_IO_PENDING, rv);
3478
3479 rv = callback1.WaitForResult();
3480 EXPECT_EQ(OK, rv);
3481
3482 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3483 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443484 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323485 EXPECT_EQ(ERR_IO_PENDING, rv);
3486 rv = callback2.WaitForResult();
3487 EXPECT_EQ(OK, rv);
3488 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3489
3490 const HttpResponseInfo* response = trans->GetResponseInfo();
3491 EXPECT_FALSE(response == NULL);
3492 // The password prompt info should have been set in response->auth_challenge.
3493 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3494
3495 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3496 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3497 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3498
3499 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443500 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323501 EXPECT_EQ(ERR_IO_PENDING, rv);
3502 rv = callback3.WaitForResult();
3503 EXPECT_EQ(OK, rv);
3504 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3505
3506 response = trans->GetResponseInfo();
3507 EXPECT_FALSE(response == NULL);
3508
3509 // There is no challenge info, since the identity worked.
3510 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3511
3512 EXPECT_EQ(100, response->headers->GetContentLength());
3513
3514 // Empty the current queue.
3515 MessageLoop::current()->RunAllPending();
3516}
3517
[email protected]f9ee6b52008-11-08 06:46:233518// Test that previously tried username/passwords for a realm get re-used.
3519TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593520 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273521 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233522
3523 // Transaction 1: authenticate (foo, bar) on MyRealm1
3524 {
[email protected]5695b8c2009-09-30 21:36:433525 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233526
[email protected]1c773ea12009-04-28 19:58:423527 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233528 request.method = "GET";
3529 request.url = GURL("http://www.google.com/x/y/z");
3530 request.load_flags = 0;
3531
3532 MockWrite data_writes1[] = {
3533 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3534 "Host: www.google.com\r\n"
3535 "Connection: keep-alive\r\n\r\n"),
3536 };
3537
3538 MockRead data_reads1[] = {
3539 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3540 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3541 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423542 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233543 };
3544
3545 // Resend with authorization (username=foo, password=bar)
3546 MockWrite data_writes2[] = {
3547 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3548 "Host: www.google.com\r\n"
3549 "Connection: keep-alive\r\n"
3550 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3551 };
3552
3553 // Sever accepts the authorization.
3554 MockRead data_reads2[] = {
3555 MockRead("HTTP/1.0 200 OK\r\n"),
3556 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423557 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233558 };
3559
[email protected]31a2bfe2010-02-09 08:03:393560 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3561 data_writes1, arraysize(data_writes1));
3562 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3563 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593564 session_deps.socket_factory.AddSocketDataProvider(&data1);
3565 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233566
3567 TestCompletionCallback callback1;
3568
[email protected]5a1d7ca2010-04-28 20:12:273569 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423570 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233571
3572 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423573 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233574
[email protected]1c773ea12009-04-28 19:58:423575 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233576 EXPECT_FALSE(response == NULL);
3577
3578 // The password prompt info should have been set in
3579 // response->auth_challenge.
3580 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3581
[email protected]71e4573a2009-05-21 22:03:003582 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233583 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3584 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3585
3586 TestCompletionCallback callback2;
3587
[email protected]13c8a092010-07-29 06:15:443588 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423589 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233590
3591 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423592 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233593
3594 response = trans->GetResponseInfo();
3595 EXPECT_FALSE(response == NULL);
3596 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3597 EXPECT_EQ(100, response->headers->GetContentLength());
3598 }
3599
3600 // ------------------------------------------------------------------------
3601
3602 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3603 {
[email protected]5695b8c2009-09-30 21:36:433604 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233605
[email protected]1c773ea12009-04-28 19:58:423606 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233607 request.method = "GET";
3608 // Note that Transaction 1 was at /x/y/z, so this is in the same
3609 // protection space as MyRealm1.
3610 request.url = GURL("http://www.google.com/x/y/a/b");
3611 request.load_flags = 0;
3612
3613 MockWrite data_writes1[] = {
3614 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3615 "Host: www.google.com\r\n"
3616 "Connection: keep-alive\r\n"
3617 // Send preemptive authorization for MyRealm1
3618 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3619 };
3620
3621 // The server didn't like the preemptive authorization, and
3622 // challenges us for a different realm (MyRealm2).
3623 MockRead data_reads1[] = {
3624 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3625 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3626 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423627 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233628 };
3629
3630 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3631 MockWrite data_writes2[] = {
3632 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3633 "Host: www.google.com\r\n"
3634 "Connection: keep-alive\r\n"
3635 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3636 };
3637
3638 // Sever accepts the authorization.
3639 MockRead data_reads2[] = {
3640 MockRead("HTTP/1.0 200 OK\r\n"),
3641 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423642 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233643 };
3644
[email protected]31a2bfe2010-02-09 08:03:393645 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3646 data_writes1, arraysize(data_writes1));
3647 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3648 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593649 session_deps.socket_factory.AddSocketDataProvider(&data1);
3650 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233651
3652 TestCompletionCallback callback1;
3653
[email protected]5a1d7ca2010-04-28 20:12:273654 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423655 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233656
3657 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423658 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233659
[email protected]1c773ea12009-04-28 19:58:423660 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233661 EXPECT_FALSE(response == NULL);
3662
3663 // The password prompt info should have been set in
3664 // response->auth_challenge.
3665 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3666
[email protected]71e4573a2009-05-21 22:03:003667 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233668 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3669 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3670
3671 TestCompletionCallback callback2;
3672
[email protected]13c8a092010-07-29 06:15:443673 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423674 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233675
3676 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423677 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233678
3679 response = trans->GetResponseInfo();
3680 EXPECT_FALSE(response == NULL);
3681 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3682 EXPECT_EQ(100, response->headers->GetContentLength());
3683 }
3684
3685 // ------------------------------------------------------------------------
3686
3687 // Transaction 3: Resend a request in MyRealm's protection space --
3688 // succeed with preemptive authorization.
3689 {
[email protected]5695b8c2009-09-30 21:36:433690 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233691
[email protected]1c773ea12009-04-28 19:58:423692 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233693 request.method = "GET";
3694 request.url = GURL("http://www.google.com/x/y/z2");
3695 request.load_flags = 0;
3696
3697 MockWrite data_writes1[] = {
3698 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3699 "Host: www.google.com\r\n"
3700 "Connection: keep-alive\r\n"
3701 // The authorization for MyRealm1 gets sent preemptively
3702 // (since the url is in the same protection space)
3703 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3704 };
3705
3706 // Sever accepts the preemptive authorization
3707 MockRead data_reads1[] = {
3708 MockRead("HTTP/1.0 200 OK\r\n"),
3709 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423710 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233711 };
3712
[email protected]31a2bfe2010-02-09 08:03:393713 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3714 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593715 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233716
3717 TestCompletionCallback callback1;
3718
[email protected]5a1d7ca2010-04-28 20:12:273719 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423720 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233721
3722 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423723 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233724
[email protected]1c773ea12009-04-28 19:58:423725 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233726 EXPECT_FALSE(response == NULL);
3727
3728 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3729 EXPECT_EQ(100, response->headers->GetContentLength());
3730 }
3731
3732 // ------------------------------------------------------------------------
3733
3734 // Transaction 4: request another URL in MyRealm (however the
3735 // url is not known to belong to the protection space, so no pre-auth).
3736 {
[email protected]5695b8c2009-09-30 21:36:433737 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233738
[email protected]1c773ea12009-04-28 19:58:423739 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233740 request.method = "GET";
3741 request.url = GURL("http://www.google.com/x/1");
3742 request.load_flags = 0;
3743
3744 MockWrite data_writes1[] = {
3745 MockWrite("GET /x/1 HTTP/1.1\r\n"
3746 "Host: www.google.com\r\n"
3747 "Connection: keep-alive\r\n\r\n"),
3748 };
3749
3750 MockRead data_reads1[] = {
3751 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3752 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3753 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423754 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233755 };
3756
3757 // Resend with authorization from MyRealm's cache.
3758 MockWrite data_writes2[] = {
3759 MockWrite("GET /x/1 HTTP/1.1\r\n"
3760 "Host: www.google.com\r\n"
3761 "Connection: keep-alive\r\n"
3762 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3763 };
3764
3765 // Sever accepts the authorization.
3766 MockRead data_reads2[] = {
3767 MockRead("HTTP/1.0 200 OK\r\n"),
3768 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423769 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233770 };
3771
[email protected]31a2bfe2010-02-09 08:03:393772 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3773 data_writes1, arraysize(data_writes1));
3774 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3775 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593776 session_deps.socket_factory.AddSocketDataProvider(&data1);
3777 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233778
3779 TestCompletionCallback callback1;
3780
[email protected]5a1d7ca2010-04-28 20:12:273781 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423782 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233783
3784 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423785 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233786
[email protected]0757e7702009-03-27 04:00:223787 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3788 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443789 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423790 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223791 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423792 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223793 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3794
[email protected]1c773ea12009-04-28 19:58:423795 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233796 EXPECT_FALSE(response == NULL);
3797 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3798 EXPECT_EQ(100, response->headers->GetContentLength());
3799 }
3800
3801 // ------------------------------------------------------------------------
3802
3803 // Transaction 5: request a URL in MyRealm, but the server rejects the
3804 // cached identity. Should invalidate and re-prompt.
3805 {
[email protected]5695b8c2009-09-30 21:36:433806 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233807
[email protected]1c773ea12009-04-28 19:58:423808 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233809 request.method = "GET";
3810 request.url = GURL("http://www.google.com/p/q/t");
3811 request.load_flags = 0;
3812
3813 MockWrite data_writes1[] = {
3814 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3815 "Host: www.google.com\r\n"
3816 "Connection: keep-alive\r\n\r\n"),
3817 };
3818
3819 MockRead data_reads1[] = {
3820 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3821 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3822 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423823 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233824 };
3825
3826 // Resend with authorization from cache for MyRealm.
3827 MockWrite data_writes2[] = {
3828 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3829 "Host: www.google.com\r\n"
3830 "Connection: keep-alive\r\n"
3831 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3832 };
3833
3834 // Sever rejects the authorization.
3835 MockRead data_reads2[] = {
3836 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3837 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3838 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423839 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233840 };
3841
3842 // At this point we should prompt for new credentials for MyRealm.
3843 // Restart with username=foo3, password=foo4.
3844 MockWrite data_writes3[] = {
3845 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3846 "Host: www.google.com\r\n"
3847 "Connection: keep-alive\r\n"
3848 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3849 };
3850
3851 // Sever accepts the authorization.
3852 MockRead data_reads3[] = {
3853 MockRead("HTTP/1.0 200 OK\r\n"),
3854 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423855 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233856 };
3857
[email protected]31a2bfe2010-02-09 08:03:393858 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3859 data_writes1, arraysize(data_writes1));
3860 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3861 data_writes2, arraysize(data_writes2));
3862 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3863 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593864 session_deps.socket_factory.AddSocketDataProvider(&data1);
3865 session_deps.socket_factory.AddSocketDataProvider(&data2);
3866 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233867
3868 TestCompletionCallback callback1;
3869
[email protected]5a1d7ca2010-04-28 20:12:273870 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423871 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233872
3873 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423874 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233875
[email protected]0757e7702009-03-27 04:00:223876 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3877 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443878 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423879 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223880 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423881 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223882 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3883
[email protected]1c773ea12009-04-28 19:58:423884 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233885 EXPECT_FALSE(response == NULL);
3886
3887 // The password prompt info should have been set in
3888 // response->auth_challenge.
3889 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3890
[email protected]71e4573a2009-05-21 22:03:003891 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233892 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3893 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3894
[email protected]0757e7702009-03-27 04:00:223895 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233896
[email protected]13c8a092010-07-29 06:15:443897 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:423898 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233899
[email protected]0757e7702009-03-27 04:00:223900 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423901 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233902
3903 response = trans->GetResponseInfo();
3904 EXPECT_FALSE(response == NULL);
3905 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3906 EXPECT_EQ(100, response->headers->GetContentLength());
3907 }
3908}
[email protected]89ceba9a2009-03-21 03:46:063909
[email protected]3c32c5f2010-05-18 15:18:123910// Tests that nonce count increments when multiple auth attempts
3911// are started with the same nonce.
3912TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3913 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273914 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:123915 HttpAuthHandlerDigest::SetFixedCnonce(true);
3916
3917 // Transaction 1: authenticate (foo, bar) on MyRealm1
3918 {
3919 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3920
3921 HttpRequestInfo request;
3922 request.method = "GET";
3923 request.url = GURL("http://www.google.com/x/y/z");
3924 request.load_flags = 0;
3925
3926 MockWrite data_writes1[] = {
3927 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3928 "Host: www.google.com\r\n"
3929 "Connection: keep-alive\r\n\r\n"),
3930 };
3931
3932 MockRead data_reads1[] = {
3933 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3934 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3935 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3936 MockRead(false, OK),
3937 };
3938
3939 // Resend with authorization (username=foo, password=bar)
3940 MockWrite data_writes2[] = {
3941 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3942 "Host: www.google.com\r\n"
3943 "Connection: keep-alive\r\n"
3944 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3945 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3946 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3947 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3948 };
3949
3950 // Sever accepts the authorization.
3951 MockRead data_reads2[] = {
3952 MockRead("HTTP/1.0 200 OK\r\n"),
3953 MockRead(false, OK),
3954 };
3955
3956 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3957 data_writes1, arraysize(data_writes1));
3958 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3959 data_writes2, arraysize(data_writes2));
3960 session_deps.socket_factory.AddSocketDataProvider(&data1);
3961 session_deps.socket_factory.AddSocketDataProvider(&data2);
3962
3963 TestCompletionCallback callback1;
3964
3965 int rv = trans->Start(&request, &callback1, BoundNetLog());
3966 EXPECT_EQ(ERR_IO_PENDING, rv);
3967
3968 rv = callback1.WaitForResult();
3969 EXPECT_EQ(OK, rv);
3970
3971 const HttpResponseInfo* response = trans->GetResponseInfo();
3972 ASSERT_FALSE(response == NULL);
3973
3974 // The password prompt info should have been set in
3975 // response->auth_challenge.
3976 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3977
3978 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3979 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3980 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3981
3982 TestCompletionCallback callback2;
3983
[email protected]13c8a092010-07-29 06:15:443984 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:123985 EXPECT_EQ(ERR_IO_PENDING, rv);
3986
3987 rv = callback2.WaitForResult();
3988 EXPECT_EQ(OK, rv);
3989
3990 response = trans->GetResponseInfo();
3991 ASSERT_FALSE(response == NULL);
3992 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3993 }
3994
3995 // ------------------------------------------------------------------------
3996
3997 // Transaction 2: Request another resource in digestive's protection space.
3998 // This will preemptively add an Authorization header which should have an
3999 // "nc" value of 2 (as compared to 1 in the first use.
4000 {
4001 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4002
4003 HttpRequestInfo request;
4004 request.method = "GET";
4005 // Note that Transaction 1 was at /x/y/z, so this is in the same
4006 // protection space as digest.
4007 request.url = GURL("http://www.google.com/x/y/a/b");
4008 request.load_flags = 0;
4009
4010 MockWrite data_writes1[] = {
4011 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4012 "Host: www.google.com\r\n"
4013 "Connection: keep-alive\r\n"
4014 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4015 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4016 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4017 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4018 };
4019
4020 // Sever accepts the authorization.
4021 MockRead data_reads1[] = {
4022 MockRead("HTTP/1.0 200 OK\r\n"),
4023 MockRead("Content-Length: 100\r\n\r\n"),
4024 MockRead(false, OK),
4025 };
4026
4027 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4028 data_writes1, arraysize(data_writes1));
4029 session_deps.socket_factory.AddSocketDataProvider(&data1);
4030
4031 TestCompletionCallback callback1;
4032
4033 int rv = trans->Start(&request, &callback1, BoundNetLog());
4034 EXPECT_EQ(ERR_IO_PENDING, rv);
4035
4036 rv = callback1.WaitForResult();
4037 EXPECT_EQ(OK, rv);
4038
4039 const HttpResponseInfo* response = trans->GetResponseInfo();
4040 ASSERT_FALSE(response == NULL);
4041 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4042 }
4043}
4044
[email protected]89ceba9a2009-03-21 03:46:064045// Test the ResetStateForRestart() private method.
4046TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4047 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594048 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404049 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434050 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064051
4052 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064053 trans->read_buf_ = new IOBuffer(15);
4054 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204055 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064056
4057 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144058 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574059 response->auth_challenge = new AuthChallengeInfo();
4060 response->ssl_info.cert_status = -15;
4061 response->response_time = base::Time::Now();
4062 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064063
4064 { // Setup state for response_.vary_data
4065 HttpRequestInfo request;
4066 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4067 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274068 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434069 request.extra_headers.SetHeader("Foo", "1");
4070 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574071 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064072 }
4073
4074 // Cause the above state to be reset.
4075 trans->ResetStateForRestart();
4076
4077 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074078 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064079 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204080 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574081 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4082 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044083 EXPECT_FALSE(response->was_cached);
[email protected]0877e3d2009-10-17 22:29:574084 EXPECT_EQ(0, response->ssl_info.cert_status);
4085 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064086}
4087
[email protected]bacff652009-03-31 17:50:334088// Test HTTPS connections to a site with a bad certificate
4089TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:594090 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404091 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434092 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334093
4094 HttpRequestInfo request;
4095 request.method = "GET";
4096 request.url = GURL("https://www.google.com/");
4097 request.load_flags = 0;
4098
4099 MockWrite data_writes[] = {
4100 MockWrite("GET / HTTP/1.1\r\n"
4101 "Host: www.google.com\r\n"
4102 "Connection: keep-alive\r\n\r\n"),
4103 };
4104
4105 MockRead data_reads[] = {
4106 MockRead("HTTP/1.0 200 OK\r\n"),
4107 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4108 MockRead("Content-Length: 100\r\n\r\n"),
4109 MockRead(false, OK),
4110 };
4111
[email protected]5ecc992a42009-11-11 01:41:594112 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394113 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4114 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594115 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4116 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334117
[email protected]5ecc992a42009-11-11 01:41:594118 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4119 session_deps.socket_factory.AddSocketDataProvider(&data);
4120 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4121 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334122
4123 TestCompletionCallback callback;
4124
[email protected]5a1d7ca2010-04-28 20:12:274125 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334126 EXPECT_EQ(ERR_IO_PENDING, rv);
4127
4128 rv = callback.WaitForResult();
4129 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4130
4131 rv = trans->RestartIgnoringLastError(&callback);
4132 EXPECT_EQ(ERR_IO_PENDING, rv);
4133
4134 rv = callback.WaitForResult();
4135 EXPECT_EQ(OK, rv);
4136
4137 const HttpResponseInfo* response = trans->GetResponseInfo();
4138
4139 EXPECT_FALSE(response == NULL);
4140 EXPECT_EQ(100, response->headers->GetContentLength());
4141}
4142
4143// Test HTTPS connections to a site with a bad certificate, going through a
4144// proxy
4145TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004146 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334147
4148 HttpRequestInfo request;
4149 request.method = "GET";
4150 request.url = GURL("https://www.google.com/");
4151 request.load_flags = 0;
4152
4153 MockWrite proxy_writes[] = {
4154 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454155 "Host: www.google.com\r\n"
4156 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334157 };
4158
4159 MockRead proxy_reads[] = {
4160 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424161 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334162 };
4163
4164 MockWrite data_writes[] = {
4165 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454166 "Host: www.google.com\r\n"
4167 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334168 MockWrite("GET / HTTP/1.1\r\n"
4169 "Host: www.google.com\r\n"
4170 "Connection: keep-alive\r\n\r\n"),
4171 };
4172
4173 MockRead data_reads[] = {
4174 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4175 MockRead("HTTP/1.0 200 OK\r\n"),
4176 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4177 MockRead("Content-Length: 100\r\n\r\n"),
4178 MockRead(false, OK),
4179 };
4180
[email protected]31a2bfe2010-02-09 08:03:394181 StaticSocketDataProvider ssl_bad_certificate(
4182 proxy_reads, arraysize(proxy_reads),
4183 proxy_writes, arraysize(proxy_writes));
4184 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4185 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594186 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4187 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334188
[email protected]5ecc992a42009-11-11 01:41:594189 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4190 session_deps.socket_factory.AddSocketDataProvider(&data);
4191 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4192 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334193
4194 TestCompletionCallback callback;
4195
4196 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594197 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334198
[email protected]d207a5f2009-06-04 05:28:404199 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434200 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334201
[email protected]5a1d7ca2010-04-28 20:12:274202 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334203 EXPECT_EQ(ERR_IO_PENDING, rv);
4204
4205 rv = callback.WaitForResult();
4206 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4207
4208 rv = trans->RestartIgnoringLastError(&callback);
4209 EXPECT_EQ(ERR_IO_PENDING, rv);
4210
4211 rv = callback.WaitForResult();
4212 EXPECT_EQ(OK, rv);
4213
4214 const HttpResponseInfo* response = trans->GetResponseInfo();
4215
4216 EXPECT_FALSE(response == NULL);
4217 EXPECT_EQ(100, response->headers->GetContentLength());
4218 }
4219}
4220
[email protected]2df19bb2010-08-25 20:13:464221
4222// Test HTTPS connections to a site, going through an HTTPS proxy
4223TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004224 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464225
4226 HttpRequestInfo request;
4227 request.method = "GET";
4228 request.url = GURL("https://www.google.com/");
4229 request.load_flags = 0;
4230
4231 MockWrite data_writes[] = {
4232 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4233 "Host: www.google.com\r\n"
4234 "Proxy-Connection: keep-alive\r\n\r\n"),
4235 MockWrite("GET / HTTP/1.1\r\n"
4236 "Host: www.google.com\r\n"
4237 "Connection: keep-alive\r\n\r\n"),
4238 };
4239
4240 MockRead data_reads[] = {
4241 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4242 MockRead("HTTP/1.1 200 OK\r\n"),
4243 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4244 MockRead("Content-Length: 100\r\n\r\n"),
4245 MockRead(false, OK),
4246 };
4247
4248 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4249 data_writes, arraysize(data_writes));
4250 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4251 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4252
4253 session_deps.socket_factory.AddSocketDataProvider(&data);
4254 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4255 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4256
4257 TestCompletionCallback callback;
4258
4259 scoped_ptr<HttpTransaction> trans(
4260 new HttpNetworkTransaction(CreateSession(&session_deps)));
4261
4262 int rv = trans->Start(&request, &callback, BoundNetLog());
4263 EXPECT_EQ(ERR_IO_PENDING, rv);
4264
4265 rv = callback.WaitForResult();
4266 EXPECT_EQ(OK, rv);
4267 const HttpResponseInfo* response = trans->GetResponseInfo();
4268
4269 ASSERT_FALSE(response == NULL);
4270
4271 EXPECT_TRUE(response->headers->IsKeepAlive());
4272 EXPECT_EQ(200, response->headers->response_code());
4273 EXPECT_EQ(100, response->headers->GetContentLength());
4274 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4275}
4276
4277// Test HTTPS connections to a site with a bad certificate, going through an
4278// HTTPS proxy
4279TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004280 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464281
4282 HttpRequestInfo request;
4283 request.method = "GET";
4284 request.url = GURL("https://www.google.com/");
4285 request.load_flags = 0;
4286
4287 // Attempt to fetch the URL from a server with a bad cert
4288 MockWrite bad_cert_writes[] = {
4289 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4290 "Host: www.google.com\r\n"
4291 "Proxy-Connection: keep-alive\r\n\r\n"),
4292 };
4293
4294 MockRead bad_cert_reads[] = {
4295 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4296 MockRead(false, OK)
4297 };
4298
4299 // Attempt to fetch the URL with a good cert
4300 MockWrite good_data_writes[] = {
4301 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4302 "Host: www.google.com\r\n"
4303 "Proxy-Connection: keep-alive\r\n\r\n"),
4304 MockWrite("GET / HTTP/1.1\r\n"
4305 "Host: www.google.com\r\n"
4306 "Connection: keep-alive\r\n\r\n"),
4307 };
4308
4309 MockRead good_cert_reads[] = {
4310 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4311 MockRead("HTTP/1.0 200 OK\r\n"),
4312 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4313 MockRead("Content-Length: 100\r\n\r\n"),
4314 MockRead(false, OK),
4315 };
4316
4317 StaticSocketDataProvider ssl_bad_certificate(
4318 bad_cert_reads, arraysize(bad_cert_reads),
4319 bad_cert_writes, arraysize(bad_cert_writes));
4320 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4321 good_data_writes, arraysize(good_data_writes));
4322 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4323 SSLSocketDataProvider ssl(true, OK);
4324
4325 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4326 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4327 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4328 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4329
4330 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4331 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4332 session_deps.socket_factory.AddSocketDataProvider(&data);
4333 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4334
4335 TestCompletionCallback callback;
4336
4337 scoped_ptr<HttpTransaction> trans(
4338 new HttpNetworkTransaction(CreateSession(&session_deps)));
4339
4340 int rv = trans->Start(&request, &callback, BoundNetLog());
4341 EXPECT_EQ(ERR_IO_PENDING, rv);
4342
4343 rv = callback.WaitForResult();
4344 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4345
4346 rv = trans->RestartIgnoringLastError(&callback);
4347 EXPECT_EQ(ERR_IO_PENDING, rv);
4348
4349 rv = callback.WaitForResult();
4350 EXPECT_EQ(OK, rv);
4351
4352 const HttpResponseInfo* response = trans->GetResponseInfo();
4353
4354 EXPECT_FALSE(response == NULL);
4355 EXPECT_EQ(100, response->headers->GetContentLength());
4356}
4357
[email protected]1c773ea12009-04-28 19:58:424358TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:594359 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404360 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434361 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424362
4363 HttpRequestInfo request;
4364 request.method = "GET";
4365 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434366 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4367 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424368
4369 MockWrite data_writes[] = {
4370 MockWrite("GET / HTTP/1.1\r\n"
4371 "Host: www.google.com\r\n"
4372 "Connection: keep-alive\r\n"
4373 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4374 };
4375
4376 // Lastly, the server responds with the actual content.
4377 MockRead data_reads[] = {
4378 MockRead("HTTP/1.0 200 OK\r\n"),
4379 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4380 MockRead("Content-Length: 100\r\n\r\n"),
4381 MockRead(false, OK),
4382 };
4383
[email protected]31a2bfe2010-02-09 08:03:394384 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4385 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594386 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424387
4388 TestCompletionCallback callback;
4389
[email protected]5a1d7ca2010-04-28 20:12:274390 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424391 EXPECT_EQ(ERR_IO_PENDING, rv);
4392
4393 rv = callback.WaitForResult();
4394 EXPECT_EQ(OK, rv);
4395}
4396
[email protected]da81f132010-08-18 23:39:294397TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]81cdfcd2010-10-16 00:49:004398 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]da81f132010-08-18 23:39:294399 scoped_ptr<HttpTransaction> trans(
4400 new HttpNetworkTransaction(CreateSession(&session_deps)));
4401
4402 HttpRequestInfo request;
4403 request.method = "GET";
4404 request.url = GURL("https://www.google.com/");
4405 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4406 "Chromium Ultra Awesome X Edition");
4407
4408 MockWrite data_writes[] = {
4409 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4410 "Host: www.google.com\r\n"
4411 "Proxy-Connection: keep-alive\r\n"
4412 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4413 };
4414 MockRead data_reads[] = {
4415 // Return an error, so the transaction stops here (this test isn't
4416 // interested in the rest).
4417 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4418 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4419 MockRead("Proxy-Connection: close\r\n\r\n"),
4420 };
4421
4422 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4423 data_writes, arraysize(data_writes));
4424 session_deps.socket_factory.AddSocketDataProvider(&data);
4425
4426 TestCompletionCallback callback;
4427
4428 int rv = trans->Start(&request, &callback, BoundNetLog());
4429 EXPECT_EQ(ERR_IO_PENDING, rv);
4430
4431 rv = callback.WaitForResult();
4432 EXPECT_EQ(OK, rv);
4433}
4434
[email protected]1c773ea12009-04-28 19:58:424435TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:594436 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404437 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434438 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424439
4440 HttpRequestInfo request;
4441 request.method = "GET";
4442 request.url = GURL("http://www.google.com/");
4443 request.load_flags = 0;
4444 request.referrer = GURL("http://the.previous.site.com/");
4445
4446 MockWrite data_writes[] = {
4447 MockWrite("GET / HTTP/1.1\r\n"
4448 "Host: www.google.com\r\n"
4449 "Connection: keep-alive\r\n"
4450 "Referer: http://the.previous.site.com/\r\n\r\n"),
4451 };
4452
4453 // Lastly, the server responds with the actual content.
4454 MockRead data_reads[] = {
4455 MockRead("HTTP/1.0 200 OK\r\n"),
4456 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4457 MockRead("Content-Length: 100\r\n\r\n"),
4458 MockRead(false, OK),
4459 };
4460
[email protected]31a2bfe2010-02-09 08:03:394461 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4462 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594463 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424464
4465 TestCompletionCallback callback;
4466
[email protected]5a1d7ca2010-04-28 20:12:274467 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424468 EXPECT_EQ(ERR_IO_PENDING, rv);
4469
4470 rv = callback.WaitForResult();
4471 EXPECT_EQ(OK, rv);
4472}
4473
4474TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594475 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404476 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434477 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424478
4479 HttpRequestInfo request;
4480 request.method = "POST";
4481 request.url = GURL("http://www.google.com/");
4482
4483 MockWrite data_writes[] = {
4484 MockWrite("POST / HTTP/1.1\r\n"
4485 "Host: www.google.com\r\n"
4486 "Connection: keep-alive\r\n"
4487 "Content-Length: 0\r\n\r\n"),
4488 };
4489
4490 // Lastly, the server responds with the actual content.
4491 MockRead data_reads[] = {
4492 MockRead("HTTP/1.0 200 OK\r\n"),
4493 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4494 MockRead("Content-Length: 100\r\n\r\n"),
4495 MockRead(false, OK),
4496 };
4497
[email protected]31a2bfe2010-02-09 08:03:394498 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4499 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594500 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424501
4502 TestCompletionCallback callback;
4503
[email protected]5a1d7ca2010-04-28 20:12:274504 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424505 EXPECT_EQ(ERR_IO_PENDING, rv);
4506
4507 rv = callback.WaitForResult();
4508 EXPECT_EQ(OK, rv);
4509}
4510
4511TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594512 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404513 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434514 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424515
4516 HttpRequestInfo request;
4517 request.method = "PUT";
4518 request.url = GURL("http://www.google.com/");
4519
4520 MockWrite data_writes[] = {
4521 MockWrite("PUT / HTTP/1.1\r\n"
4522 "Host: www.google.com\r\n"
4523 "Connection: keep-alive\r\n"
4524 "Content-Length: 0\r\n\r\n"),
4525 };
4526
4527 // Lastly, the server responds with the actual content.
4528 MockRead data_reads[] = {
4529 MockRead("HTTP/1.0 200 OK\r\n"),
4530 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4531 MockRead("Content-Length: 100\r\n\r\n"),
4532 MockRead(false, OK),
4533 };
4534
[email protected]31a2bfe2010-02-09 08:03:394535 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4536 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594537 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424538
4539 TestCompletionCallback callback;
4540
[email protected]5a1d7ca2010-04-28 20:12:274541 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424542 EXPECT_EQ(ERR_IO_PENDING, rv);
4543
4544 rv = callback.WaitForResult();
4545 EXPECT_EQ(OK, rv);
4546}
4547
4548TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594549 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404550 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434551 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424552
4553 HttpRequestInfo request;
4554 request.method = "HEAD";
4555 request.url = GURL("http://www.google.com/");
4556
4557 MockWrite data_writes[] = {
4558 MockWrite("HEAD / HTTP/1.1\r\n"
4559 "Host: www.google.com\r\n"
4560 "Connection: keep-alive\r\n"
4561 "Content-Length: 0\r\n\r\n"),
4562 };
4563
4564 // Lastly, the server responds with the actual content.
4565 MockRead data_reads[] = {
4566 MockRead("HTTP/1.0 200 OK\r\n"),
4567 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4568 MockRead("Content-Length: 100\r\n\r\n"),
4569 MockRead(false, OK),
4570 };
4571
[email protected]31a2bfe2010-02-09 08:03:394572 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4573 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594574 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424575
4576 TestCompletionCallback callback;
4577
[email protected]5a1d7ca2010-04-28 20:12:274578 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424579 EXPECT_EQ(ERR_IO_PENDING, rv);
4580
4581 rv = callback.WaitForResult();
4582 EXPECT_EQ(OK, rv);
4583}
4584
4585TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:594586 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404587 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434588 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424589
4590 HttpRequestInfo request;
4591 request.method = "GET";
4592 request.url = GURL("http://www.google.com/");
4593 request.load_flags = LOAD_BYPASS_CACHE;
4594
4595 MockWrite data_writes[] = {
4596 MockWrite("GET / HTTP/1.1\r\n"
4597 "Host: www.google.com\r\n"
4598 "Connection: keep-alive\r\n"
4599 "Pragma: no-cache\r\n"
4600 "Cache-Control: no-cache\r\n\r\n"),
4601 };
4602
4603 // Lastly, the server responds with the actual content.
4604 MockRead data_reads[] = {
4605 MockRead("HTTP/1.0 200 OK\r\n"),
4606 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4607 MockRead("Content-Length: 100\r\n\r\n"),
4608 MockRead(false, OK),
4609 };
4610
[email protected]31a2bfe2010-02-09 08:03:394611 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4612 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594613 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424614
4615 TestCompletionCallback callback;
4616
[email protected]5a1d7ca2010-04-28 20:12:274617 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424618 EXPECT_EQ(ERR_IO_PENDING, rv);
4619
4620 rv = callback.WaitForResult();
4621 EXPECT_EQ(OK, rv);
4622}
4623
4624TEST_F(HttpNetworkTransactionTest,
4625 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:594626 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404627 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434628 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424629
4630 HttpRequestInfo request;
4631 request.method = "GET";
4632 request.url = GURL("http://www.google.com/");
4633 request.load_flags = LOAD_VALIDATE_CACHE;
4634
4635 MockWrite data_writes[] = {
4636 MockWrite("GET / HTTP/1.1\r\n"
4637 "Host: www.google.com\r\n"
4638 "Connection: keep-alive\r\n"
4639 "Cache-Control: max-age=0\r\n\r\n"),
4640 };
4641
4642 // Lastly, the server responds with the actual content.
4643 MockRead data_reads[] = {
4644 MockRead("HTTP/1.0 200 OK\r\n"),
4645 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4646 MockRead("Content-Length: 100\r\n\r\n"),
4647 MockRead(false, OK),
4648 };
4649
[email protected]31a2bfe2010-02-09 08:03:394650 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4651 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594652 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424653
4654 TestCompletionCallback callback;
4655
[email protected]5a1d7ca2010-04-28 20:12:274656 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424657 EXPECT_EQ(ERR_IO_PENDING, rv);
4658
4659 rv = callback.WaitForResult();
4660 EXPECT_EQ(OK, rv);
4661}
4662
4663TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:594664 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404665 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434666 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424667
4668 HttpRequestInfo request;
4669 request.method = "GET";
4670 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434671 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:424672
4673 MockWrite data_writes[] = {
4674 MockWrite("GET / HTTP/1.1\r\n"
4675 "Host: www.google.com\r\n"
4676 "Connection: keep-alive\r\n"
4677 "FooHeader: Bar\r\n\r\n"),
4678 };
4679
4680 // Lastly, the server responds with the actual content.
4681 MockRead data_reads[] = {
4682 MockRead("HTTP/1.0 200 OK\r\n"),
4683 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4684 MockRead("Content-Length: 100\r\n\r\n"),
4685 MockRead(false, OK),
4686 };
4687
[email protected]31a2bfe2010-02-09 08:03:394688 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4689 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594690 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424691
4692 TestCompletionCallback callback;
4693
[email protected]5a1d7ca2010-04-28 20:12:274694 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424695 EXPECT_EQ(ERR_IO_PENDING, rv);
4696
4697 rv = callback.WaitForResult();
4698 EXPECT_EQ(OK, rv);
4699}
4700
[email protected]270c6412010-03-29 22:02:474701TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
4702 SessionDependencies session_deps;
4703 scoped_ptr<HttpTransaction> trans(
4704 new HttpNetworkTransaction(CreateSession(&session_deps)));
4705
4706 HttpRequestInfo request;
4707 request.method = "GET";
4708 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434709 request.extra_headers.SetHeader("referer", "www.foo.com");
4710 request.extra_headers.SetHeader("hEllo", "Kitty");
4711 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:474712
4713 MockWrite data_writes[] = {
4714 MockWrite("GET / HTTP/1.1\r\n"
4715 "Host: www.google.com\r\n"
4716 "Connection: keep-alive\r\n"
4717 "hEllo: Kitty\r\n"
4718 "FoO: bar\r\n\r\n"),
4719 };
4720
4721 // Lastly, the server responds with the actual content.
4722 MockRead data_reads[] = {
4723 MockRead("HTTP/1.0 200 OK\r\n"),
4724 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4725 MockRead("Content-Length: 100\r\n\r\n"),
4726 MockRead(false, OK),
4727 };
4728
4729 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4730 data_writes, arraysize(data_writes));
4731 session_deps.socket_factory.AddSocketDataProvider(&data);
4732
4733 TestCompletionCallback callback;
4734
[email protected]5a1d7ca2010-04-28 20:12:274735 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:474736 EXPECT_EQ(ERR_IO_PENDING, rv);
4737
4738 rv = callback.WaitForResult();
4739 EXPECT_EQ(OK, rv);
4740}
4741
[email protected]3cd17242009-06-23 02:59:024742TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094743 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004744 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024745
4746 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434747 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024748
4749 HttpRequestInfo request;
4750 request.method = "GET";
4751 request.url = GURL("http://www.google.com/");
4752 request.load_flags = 0;
4753
4754 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
4755 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4756
4757 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354758 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024759 MockWrite("GET / HTTP/1.1\r\n"
4760 "Host: www.google.com\r\n"
4761 "Connection: keep-alive\r\n\r\n")
4762 };
4763
4764 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:594765 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:024766 MockRead("HTTP/1.0 200 OK\r\n"),
4767 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4768 MockRead("Payload"),
4769 MockRead(false, OK)
4770 };
4771
[email protected]31a2bfe2010-02-09 08:03:394772 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4773 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594774 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024775
4776 TestCompletionCallback callback;
4777
[email protected]5a1d7ca2010-04-28 20:12:274778 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024779 EXPECT_EQ(ERR_IO_PENDING, rv);
4780
4781 rv = callback.WaitForResult();
4782 EXPECT_EQ(OK, rv);
4783
4784 const HttpResponseInfo* response = trans->GetResponseInfo();
4785 EXPECT_FALSE(response == NULL);
4786
4787 std::string response_text;
4788 rv = ReadTransaction(trans.get(), &response_text);
4789 EXPECT_EQ(OK, rv);
4790 EXPECT_EQ("Payload", response_text);
4791}
4792
4793TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094794 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004795 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024796
4797 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434798 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024799
4800 HttpRequestInfo request;
4801 request.method = "GET";
4802 request.url = GURL("https://www.google.com/");
4803 request.load_flags = 0;
4804
4805 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
4806 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4807
4808 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354809 MockWrite(true, reinterpret_cast<char*>(write_buffer),
4810 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024811 MockWrite("GET / HTTP/1.1\r\n"
4812 "Host: www.google.com\r\n"
4813 "Connection: keep-alive\r\n\r\n")
4814 };
4815
4816 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:354817 MockWrite(true, reinterpret_cast<char*>(read_buffer),
4818 arraysize(read_buffer)),
4819 MockRead("HTTP/1.0 200 OK\r\n"),
4820 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4821 MockRead("Payload"),
4822 MockRead(false, OK)
4823 };
4824
[email protected]31a2bfe2010-02-09 08:03:394825 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4826 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594827 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354828
[email protected]5ecc992a42009-11-11 01:41:594829 SSLSocketDataProvider ssl(true, OK);
4830 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:354831
4832 TestCompletionCallback callback;
4833
[email protected]5a1d7ca2010-04-28 20:12:274834 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354835 EXPECT_EQ(ERR_IO_PENDING, rv);
4836
4837 rv = callback.WaitForResult();
4838 EXPECT_EQ(OK, rv);
4839
4840 const HttpResponseInfo* response = trans->GetResponseInfo();
4841 EXPECT_FALSE(response == NULL);
4842
4843 std::string response_text;
4844 rv = ReadTransaction(trans.get(), &response_text);
4845 EXPECT_EQ(OK, rv);
4846 EXPECT_EQ("Payload", response_text);
4847}
4848
4849TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094850 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004851 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354852
4853 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434854 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354855
4856 HttpRequestInfo request;
4857 request.method = "GET";
4858 request.url = GURL("http://www.google.com/");
4859 request.load_flags = 0;
4860
4861 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4862 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374863 const char kSOCKS5OkRequest[] = {
4864 0x05, // Version
4865 0x01, // Command (CONNECT)
4866 0x00, // Reserved.
4867 0x03, // Address type (DOMAINNAME).
4868 0x0E, // Length of domain (14)
4869 // Domain string:
4870 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4871 0x00, 0x50, // 16-bit port (80)
4872 };
[email protected]e0c27be2009-07-15 13:09:354873 const char kSOCKS5OkResponse[] =
4874 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
4875
4876 MockWrite data_writes[] = {
4877 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4878 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
4879 MockWrite("GET / HTTP/1.1\r\n"
4880 "Host: www.google.com\r\n"
4881 "Connection: keep-alive\r\n\r\n")
4882 };
4883
4884 MockRead data_reads[] = {
4885 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4886 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
4887 MockRead("HTTP/1.0 200 OK\r\n"),
4888 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4889 MockRead("Payload"),
4890 MockRead(false, OK)
4891 };
4892
[email protected]31a2bfe2010-02-09 08:03:394893 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4894 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594895 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354896
4897 TestCompletionCallback callback;
4898
[email protected]5a1d7ca2010-04-28 20:12:274899 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354900 EXPECT_EQ(ERR_IO_PENDING, rv);
4901
4902 rv = callback.WaitForResult();
4903 EXPECT_EQ(OK, rv);
4904
4905 const HttpResponseInfo* response = trans->GetResponseInfo();
4906 EXPECT_FALSE(response == NULL);
4907
4908 std::string response_text;
4909 rv = ReadTransaction(trans.get(), &response_text);
4910 EXPECT_EQ(OK, rv);
4911 EXPECT_EQ("Payload", response_text);
4912}
4913
4914TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094915 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004916 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354917
4918 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434919 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354920
4921 HttpRequestInfo request;
4922 request.method = "GET";
4923 request.url = GURL("https://www.google.com/");
4924 request.load_flags = 0;
4925
4926 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4927 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374928 const unsigned char kSOCKS5OkRequest[] = {
4929 0x05, // Version
4930 0x01, // Command (CONNECT)
4931 0x00, // Reserved.
4932 0x03, // Address type (DOMAINNAME).
4933 0x0E, // Length of domain (14)
4934 // Domain string:
4935 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4936 0x01, 0xBB, // 16-bit port (443)
4937 };
4938
[email protected]e0c27be2009-07-15 13:09:354939 const char kSOCKS5OkResponse[] =
4940 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
4941
4942 MockWrite data_writes[] = {
4943 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4944 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
4945 arraysize(kSOCKS5OkRequest)),
4946 MockWrite("GET / HTTP/1.1\r\n"
4947 "Host: www.google.com\r\n"
4948 "Connection: keep-alive\r\n\r\n")
4949 };
4950
4951 MockRead data_reads[] = {
4952 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4953 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:024954 MockRead("HTTP/1.0 200 OK\r\n"),
4955 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4956 MockRead("Payload"),
4957 MockRead(false, OK)
4958 };
4959
[email protected]31a2bfe2010-02-09 08:03:394960 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4961 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594962 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024963
[email protected]5ecc992a42009-11-11 01:41:594964 SSLSocketDataProvider ssl(true, OK);
4965 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:024966
4967 TestCompletionCallback callback;
4968
[email protected]5a1d7ca2010-04-28 20:12:274969 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024970 EXPECT_EQ(ERR_IO_PENDING, rv);
4971
4972 rv = callback.WaitForResult();
4973 EXPECT_EQ(OK, rv);
4974
4975 const HttpResponseInfo* response = trans->GetResponseInfo();
4976 EXPECT_FALSE(response == NULL);
4977
4978 std::string response_text;
4979 rv = ReadTransaction(trans.get(), &response_text);
4980 EXPECT_EQ(OK, rv);
4981 EXPECT_EQ("Payload", response_text);
4982}
4983
[email protected]04e5be32009-06-26 20:00:314984// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:064985
4986struct GroupNameTest {
4987 std::string proxy_server;
4988 std::string url;
4989 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:184990 bool ssl;
[email protected]2d731a32010-04-29 01:04:064991};
4992
4993scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
4994 const std::string& proxy_server) {
[email protected]81cdfcd2010-10-16 00:49:004995 SessionDependencies session_deps(ProxyService::CreateFixed(proxy_server));
[email protected]2d731a32010-04-29 01:04:064996 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4997
4998 HttpAlternateProtocols* alternate_protocols =
4999 session->mutable_alternate_protocols();
5000 alternate_protocols->SetAlternateProtocolFor(
5001 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:355002 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065003
5004 return session;
5005}
5006
5007int GroupNameTransactionHelper(
5008 const std::string& url,
5009 const scoped_refptr<HttpNetworkSession>& session) {
5010 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5011
5012 HttpRequestInfo request;
5013 request.method = "GET";
5014 request.url = GURL(url);
5015 request.load_flags = 0;
5016
5017 TestCompletionCallback callback;
5018
5019 // We do not complete this request, the dtor will clean the transaction up.
5020 return trans->Start(&request, &callback, BoundNetLog());
5021}
5022
5023TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5024 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315025 {
[email protected]2d731a32010-04-29 01:04:065026 "", // unused
[email protected]04e5be32009-06-26 20:00:315027 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545028 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185029 false,
[email protected]2ff8b312010-04-26 22:20:545030 },
5031 {
[email protected]2d731a32010-04-29 01:04:065032 "", // unused
[email protected]2ff8b312010-04-26 22:20:545033 "http://[2001:1418:13:1::25]/direct",
5034 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185035 false,
[email protected]04e5be32009-06-26 20:00:315036 },
[email protected]04e5be32009-06-26 20:00:315037
5038 // SSL Tests
5039 {
[email protected]2d731a32010-04-29 01:04:065040 "", // unused
[email protected]04e5be32009-06-26 20:00:315041 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025042 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185043 true,
[email protected]04e5be32009-06-26 20:00:315044 },
5045 {
[email protected]2d731a32010-04-29 01:04:065046 "", // unused
5047 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025048 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185049 true,
[email protected]04e5be32009-06-26 20:00:315050 },
5051 {
[email protected]2d731a32010-04-29 01:04:065052 "", // unused
[email protected]2ff8b312010-04-26 22:20:545053 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025054 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185055 true,
[email protected]2ff8b312010-04-26 22:20:545056 },
[email protected]2d731a32010-04-29 01:04:065057 };
[email protected]2ff8b312010-04-26 22:20:545058
[email protected]8e6441ca2010-08-19 05:56:385059 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065060
5061 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5062 scoped_refptr<HttpNetworkSession> session(
5063 SetupSessionForGroupNameTests(tests[i].proxy_server));
5064
5065 HttpNetworkSessionPeer peer(session);
[email protected]2431756e2010-09-29 20:26:135066 CaptureGroupNameTCPSocketPool* tcp_conn_pool =
5067 new CaptureGroupNameTCPSocketPool(session);
[email protected]2d731a32010-04-29 01:04:065068 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]2431756e2010-09-29 20:26:135069 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5070 new CaptureGroupNameSSLSocketPool(session.get());
[email protected]e60e47a2010-07-14 03:37:185071 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065072
5073 EXPECT_EQ(ERR_IO_PENDING,
5074 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185075 if (tests[i].ssl)
5076 EXPECT_EQ(tests[i].expected_group_name,
5077 ssl_conn_pool->last_group_name_received());
5078 else
5079 EXPECT_EQ(tests[i].expected_group_name,
5080 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065081 }
5082
[email protected]8e6441ca2010-08-19 05:56:385083 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065084}
5085
5086TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5087 const GroupNameTest tests[] = {
5088 {
5089 "http_proxy",
5090 "http://www.google.com/http_proxy_normal",
5091 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185092 false,
[email protected]2d731a32010-04-29 01:04:065093 },
5094
5095 // SSL Tests
5096 {
5097 "http_proxy",
5098 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025099 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185100 true,
[email protected]2d731a32010-04-29 01:04:065101 },
[email protected]af3490e2010-10-16 21:02:295102
[email protected]9faeded92010-04-29 20:03:055103 {
5104 "http_proxy",
5105 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025106 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185107 true,
[email protected]9faeded92010-04-29 20:03:055108 },
[email protected]2d731a32010-04-29 01:04:065109 };
5110
[email protected]8e6441ca2010-08-19 05:56:385111 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065112
5113 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5114 scoped_refptr<HttpNetworkSession> session(
5115 SetupSessionForGroupNameTests(tests[i].proxy_server));
5116
5117 HttpNetworkSessionPeer peer(session);
5118
[email protected]e60e47a2010-07-14 03:37:185119 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135120 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
5121 new CaptureGroupNameHttpProxySocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185122 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135123 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5124 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185125 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065126
5127 EXPECT_EQ(ERR_IO_PENDING,
5128 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185129 if (tests[i].ssl)
5130 EXPECT_EQ(tests[i].expected_group_name,
5131 ssl_conn_pool->last_group_name_received());
5132 else
5133 EXPECT_EQ(tests[i].expected_group_name,
5134 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065135 }
5136
[email protected]8e6441ca2010-08-19 05:56:385137 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065138}
5139
5140TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5141 const GroupNameTest tests[] = {
5142 {
5143 "socks4://socks_proxy:1080",
5144 "http://www.google.com/socks4_direct",
5145 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185146 false,
[email protected]2d731a32010-04-29 01:04:065147 },
5148 {
5149 "socks5://socks_proxy:1080",
5150 "http://www.google.com/socks5_direct",
5151 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185152 false,
[email protected]2d731a32010-04-29 01:04:065153 },
5154
5155 // SSL Tests
5156 {
5157 "socks4://socks_proxy:1080",
5158 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025159 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185160 true,
[email protected]2d731a32010-04-29 01:04:065161 },
5162 {
5163 "socks5://socks_proxy:1080",
5164 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025165 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185166 true,
[email protected]2d731a32010-04-29 01:04:065167 },
[email protected]af3490e2010-10-16 21:02:295168
[email protected]9faeded92010-04-29 20:03:055169 {
5170 "socks4://socks_proxy:1080",
5171 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025172 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185173 true,
[email protected]9faeded92010-04-29 20:03:055174 },
[email protected]04e5be32009-06-26 20:00:315175 };
5176
[email protected]8e6441ca2010-08-19 05:56:385177 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545178
[email protected]04e5be32009-06-26 20:00:315179 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:065180 scoped_refptr<HttpNetworkSession> session(
5181 SetupSessionForGroupNameTests(tests[i].proxy_server));
5182 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315183
[email protected]e60e47a2010-07-14 03:37:185184 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135185 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
5186 new CaptureGroupNameSOCKSSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185187 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135188 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5189 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185190 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315191
[email protected]5695b8c2009-09-30 21:36:435192 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315193
[email protected]2d731a32010-04-29 01:04:065194 EXPECT_EQ(ERR_IO_PENDING,
5195 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185196 if (tests[i].ssl)
5197 EXPECT_EQ(tests[i].expected_group_name,
5198 ssl_conn_pool->last_group_name_received());
5199 else
5200 EXPECT_EQ(tests[i].expected_group_name,
5201 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315202 }
[email protected]2ff8b312010-04-26 22:20:545203
[email protected]8e6441ca2010-08-19 05:56:385204 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315205}
5206
[email protected]9172a982009-06-06 00:30:255207TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:545208 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005209 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325210
[email protected]69719062010-01-05 20:09:215211 // This simulates failure resolving all hostnames; that means we will fail
5212 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325213 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5214
[email protected]9172a982009-06-06 00:30:255215 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435216 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255217
5218 HttpRequestInfo request;
5219 request.method = "GET";
5220 request.url = GURL("http://www.google.com/");
5221
5222 TestCompletionCallback callback;
5223
[email protected]5a1d7ca2010-04-28 20:12:275224 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255225 EXPECT_EQ(ERR_IO_PENDING, rv);
5226
[email protected]9172a982009-06-06 00:30:255227 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015228 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255229}
5230
[email protected]f3e6c1e2009-06-15 20:52:125231// Host resolution observer used by
5232// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5233// resovle requests are issued with a referrer of |expected_referrer|.
5234class ResolutionReferrerObserver : public HostResolver::Observer {
5235 public:
5236 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5237 : expected_referrer_(expected_referrer),
5238 called_start_with_referrer_(false),
5239 called_finish_with_referrer_(false) {
5240 }
5241
5242 virtual void OnStartResolution(int id,
5243 const HostResolver::RequestInfo& info) {
5244 if (info.referrer() == expected_referrer_)
5245 called_start_with_referrer_ = true;
5246 }
5247
5248 virtual void OnFinishResolutionWithStatus(
5249 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5250 if (info.referrer() == expected_referrer_)
5251 called_finish_with_referrer_ = true;
5252 }
5253
[email protected]eb255d32009-06-17 02:11:035254 virtual void OnCancelResolution(int id,
5255 const HostResolver::RequestInfo& info ) {
5256 FAIL() << "Should not be cancelling any requests!";
5257 }
5258
[email protected]f3e6c1e2009-06-15 20:52:125259 bool did_complete_with_expected_referrer() const {
5260 return called_start_with_referrer_ && called_finish_with_referrer_;
5261 }
5262
5263 private:
5264 GURL expected_referrer_;
5265 bool called_start_with_referrer_;
5266 bool called_finish_with_referrer_;
5267
5268 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5269};
5270
5271// Make sure that when HostResolver::Resolve() is invoked, it passes through
5272// the "referrer". This is depended on by the DNS prefetch observer.
5273TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5274 GURL referrer = GURL("http://expected-referrer/");
5275 EXPECT_TRUE(referrer.is_valid());
5276 ResolutionReferrerObserver resolution_observer(referrer);
5277
5278 SessionDependencies session_deps;
5279 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435280 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125281
5282 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145283 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125284
5285 // Connect up a mock socket which will fail when reading.
5286 MockRead data_reads[] = {
5287 MockRead(false, ERR_FAILED),
5288 };
[email protected]31a2bfe2010-02-09 08:03:395289 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595290 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125291
5292 // Issue a request, containing an HTTP referrer.
5293 HttpRequestInfo request;
5294 request.method = "GET";
5295 request.referrer = referrer;
5296 request.url = GURL("http://www.google.com/");
5297
5298 // Run the request until it fails reading from the socket.
5299 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275300 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125301 EXPECT_EQ(ERR_IO_PENDING, rv);
5302 rv = callback.WaitForResult();
5303 EXPECT_EQ(ERR_FAILED, rv);
5304
5305 // Check that the host resolution observer saw |referrer|.
5306 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5307}
5308
[email protected]685af592010-05-11 19:31:245309// Base test to make sure that when the load flags for a request specify to
5310// bypass the cache, the DNS cache is not used.
5311void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:285312 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325313
[email protected]a2c2fb92009-07-18 07:31:045314 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545315 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325316
[email protected]3b9cca42009-06-16 01:08:285317 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435318 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285319
5320 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5321 // a synchronous lookup.)
5322 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145323 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105324 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275325 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285326 EXPECT_EQ(OK, rv);
5327
5328 // Verify that it was added to host cache, by doing a subsequent async lookup
5329 // and confirming it completes synchronously.
5330 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465331 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105332 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275333 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325334 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285335
5336 // Inject a failure the next time that "www.google.com" is resolved. This way
5337 // we can tell if the next lookup hit the cache, or the "network".
5338 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325339 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285340
5341 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5342 // first read -- this won't be reached as the host resolution will fail first.
5343 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395344 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595345 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285346
5347 // Issue a request, asking to bypass the cache(s).
5348 HttpRequestInfo request;
5349 request.method = "GET";
[email protected]685af592010-05-11 19:31:245350 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:285351 request.url = GURL("http://www.google.com/");
5352
5353 // Run the request.
5354 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275355 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285356 ASSERT_EQ(ERR_IO_PENDING, rv);
5357 rv = callback.WaitForResult();
5358
5359 // If we bypassed the cache, we would have gotten a failure while resolving
5360 // "www.google.com".
5361 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5362}
5363
[email protected]685af592010-05-11 19:31:245364// There are multiple load flags that should trigger the host cache bypass.
5365// Test each in isolation:
5366TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5367 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5368}
5369
5370TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5371 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5372}
5373
5374TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5375 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5376}
5377
[email protected]0877e3d2009-10-17 22:29:575378// Make sure we can handle an error when writing the request.
5379TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5380 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275381 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575382
5383 HttpRequestInfo request;
5384 request.method = "GET";
5385 request.url = GURL("http://www.foo.com/");
5386 request.load_flags = 0;
5387
5388 MockWrite write_failure[] = {
5389 MockWrite(true, ERR_CONNECTION_RESET),
5390 };
[email protected]31a2bfe2010-02-09 08:03:395391 StaticSocketDataProvider data(NULL, 0,
5392 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595393 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575394
5395 TestCompletionCallback callback;
5396
5397 scoped_ptr<HttpTransaction> trans(
5398 new HttpNetworkTransaction(CreateSession(&session_deps)));
5399
[email protected]5a1d7ca2010-04-28 20:12:275400 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575401 EXPECT_EQ(ERR_IO_PENDING, rv);
5402
5403 rv = callback.WaitForResult();
5404 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5405}
5406
5407// Check that a connection closed after the start of the headers finishes ok.
5408TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5409 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275410 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575411
5412 HttpRequestInfo request;
5413 request.method = "GET";
5414 request.url = GURL("http://www.foo.com/");
5415 request.load_flags = 0;
5416
5417 MockRead data_reads[] = {
5418 MockRead("HTTP/1."),
5419 MockRead(false, OK),
5420 };
5421
[email protected]31a2bfe2010-02-09 08:03:395422 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595423 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575424
5425 TestCompletionCallback callback;
5426
5427 scoped_ptr<HttpTransaction> trans(
5428 new HttpNetworkTransaction(CreateSession(&session_deps)));
5429
[email protected]5a1d7ca2010-04-28 20:12:275430 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575431 EXPECT_EQ(ERR_IO_PENDING, rv);
5432
5433 rv = callback.WaitForResult();
5434 EXPECT_EQ(OK, rv);
5435
5436 const HttpResponseInfo* response = trans->GetResponseInfo();
5437 EXPECT_TRUE(response != NULL);
5438
5439 EXPECT_TRUE(response->headers != NULL);
5440 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5441
5442 std::string response_data;
5443 rv = ReadTransaction(trans.get(), &response_data);
5444 EXPECT_EQ(OK, rv);
5445 EXPECT_EQ("", response_data);
5446}
5447
5448// Make sure that a dropped connection while draining the body for auth
5449// restart does the right thing.
5450TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5451 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275452 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575453
5454 HttpRequestInfo request;
5455 request.method = "GET";
5456 request.url = GURL("http://www.google.com/");
5457 request.load_flags = 0;
5458
5459 MockWrite data_writes1[] = {
5460 MockWrite("GET / HTTP/1.1\r\n"
5461 "Host: www.google.com\r\n"
5462 "Connection: keep-alive\r\n\r\n"),
5463 };
5464
5465 MockRead data_reads1[] = {
5466 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5467 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5468 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5469 MockRead("Content-Length: 14\r\n\r\n"),
5470 MockRead("Unauth"),
5471 MockRead(true, ERR_CONNECTION_RESET),
5472 };
5473
[email protected]31a2bfe2010-02-09 08:03:395474 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5475 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595476 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575477
5478 // After calling trans->RestartWithAuth(), this is the request we should
5479 // be issuing -- the final header line contains the credentials.
5480 MockWrite data_writes2[] = {
5481 MockWrite("GET / HTTP/1.1\r\n"
5482 "Host: www.google.com\r\n"
5483 "Connection: keep-alive\r\n"
5484 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5485 };
5486
5487 // Lastly, the server responds with the actual content.
5488 MockRead data_reads2[] = {
5489 MockRead("HTTP/1.1 200 OK\r\n"),
5490 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5491 MockRead("Content-Length: 100\r\n\r\n"),
5492 MockRead(false, OK),
5493 };
5494
[email protected]31a2bfe2010-02-09 08:03:395495 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5496 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595497 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575498
5499 TestCompletionCallback callback1;
5500
[email protected]0b0bf032010-09-21 18:08:505501 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5502
[email protected]5a1d7ca2010-04-28 20:12:275503 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575504 EXPECT_EQ(ERR_IO_PENDING, rv);
5505
5506 rv = callback1.WaitForResult();
5507 EXPECT_EQ(OK, rv);
5508
5509 const HttpResponseInfo* response = trans->GetResponseInfo();
5510 EXPECT_FALSE(response == NULL);
5511
5512 // The password prompt info should have been set in response->auth_challenge.
5513 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5514
5515 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5516 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5517 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5518
5519 TestCompletionCallback callback2;
5520
[email protected]13c8a092010-07-29 06:15:445521 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:575522 EXPECT_EQ(ERR_IO_PENDING, rv);
5523
5524 rv = callback2.WaitForResult();
5525 EXPECT_EQ(OK, rv);
5526
5527 response = trans->GetResponseInfo();
5528 EXPECT_FALSE(response == NULL);
5529 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5530 EXPECT_EQ(100, response->headers->GetContentLength());
5531}
5532
5533// Test HTTPS connections going through a proxy that sends extra data.
5534TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:005535 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:575536
5537 HttpRequestInfo request;
5538 request.method = "GET";
5539 request.url = GURL("https://www.google.com/");
5540 request.load_flags = 0;
5541
5542 MockRead proxy_reads[] = {
5543 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5544 MockRead(false, OK)
5545 };
5546
[email protected]31a2bfe2010-02-09 08:03:395547 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595548 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575549
[email protected]5ecc992a42009-11-11 01:41:595550 session_deps.socket_factory.AddSocketDataProvider(&data);
5551 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575552
5553 TestCompletionCallback callback;
5554
5555 session_deps.socket_factory.ResetNextMockIndexes();
5556
5557 scoped_ptr<HttpTransaction> trans(
5558 new HttpNetworkTransaction(CreateSession(&session_deps)));
5559
[email protected]5a1d7ca2010-04-28 20:12:275560 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575561 EXPECT_EQ(ERR_IO_PENDING, rv);
5562
5563 rv = callback.WaitForResult();
5564 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5565}
5566
[email protected]e22e1362009-11-23 21:31:125567TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:465568 SessionDependencies session_deps;
5569 scoped_ptr<HttpTransaction> trans(
5570 new HttpNetworkTransaction(CreateSession(&session_deps)));
5571
5572 HttpRequestInfo request;
5573 request.method = "GET";
5574 request.url = GURL("http://www.google.com/");
5575 request.load_flags = 0;
5576
[email protected]e22e1362009-11-23 21:31:125577 MockRead data_reads[] = {
5578 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
5579 MockRead(false, OK),
5580 };
[email protected]9492e4a2010-02-24 00:58:465581
5582 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5583 session_deps.socket_factory.AddSocketDataProvider(&data);
5584
5585 TestCompletionCallback callback;
5586
[email protected]5a1d7ca2010-04-28 20:12:275587 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:465588 EXPECT_EQ(ERR_IO_PENDING, rv);
5589
5590 EXPECT_EQ(OK, callback.WaitForResult());
5591
5592 const HttpResponseInfo* response = trans->GetResponseInfo();
5593 EXPECT_TRUE(response != NULL);
5594
5595 EXPECT_TRUE(response->headers != NULL);
5596 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5597
5598 std::string response_data;
5599 rv = ReadTransaction(trans.get(), &response_data);
5600 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:125601}
5602
[email protected]95d88ffe2010-02-04 21:25:335603TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
5604 SessionDependencies session_deps;
5605 scoped_ptr<HttpTransaction> trans(
5606 new HttpNetworkTransaction(CreateSession(&session_deps)));
5607
5608 HttpRequestInfo request;
5609 request.method = "POST";
5610 request.url = GURL("http://www.google.com/upload");
5611 request.upload_data = new UploadData;
5612 request.load_flags = 0;
5613
5614 FilePath temp_file_path;
5615 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
5616 const uint64 kFakeSize = 100000; // file is actually blank
5617
5618 std::vector<UploadData::Element> elements;
5619 UploadData::Element element;
5620 element.SetToFilePath(temp_file_path);
5621 element.SetContentLength(kFakeSize);
5622 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535623 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:335624 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
5625
5626 MockRead data_reads[] = {
5627 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5628 MockRead("hello world"),
5629 MockRead(false, OK),
5630 };
[email protected]31a2bfe2010-02-09 08:03:395631 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:335632 session_deps.socket_factory.AddSocketDataProvider(&data);
5633
5634 TestCompletionCallback callback;
5635
[email protected]5a1d7ca2010-04-28 20:12:275636 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:335637 EXPECT_EQ(ERR_IO_PENDING, rv);
5638
5639 rv = callback.WaitForResult();
5640 EXPECT_EQ(OK, rv);
5641
5642 const HttpResponseInfo* response = trans->GetResponseInfo();
5643 EXPECT_TRUE(response != NULL);
5644
5645 EXPECT_TRUE(response->headers != NULL);
5646 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5647
5648 std::string response_data;
5649 rv = ReadTransaction(trans.get(), &response_data);
5650 EXPECT_EQ(OK, rv);
5651 EXPECT_EQ("hello world", response_data);
5652
5653 file_util::Delete(temp_file_path, false);
5654}
5655
[email protected]6624b4622010-03-29 19:58:365656TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
5657 // If we try to upload an unreadable file, the network stack should report
5658 // the file size as zero and upload zero bytes for that file.
5659 SessionDependencies session_deps;
5660 scoped_ptr<HttpTransaction> trans(
5661 new HttpNetworkTransaction(CreateSession(&session_deps)));
5662
5663 FilePath temp_file;
5664 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5665 std::string temp_file_content("Unreadable file.");
5666 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
5667 temp_file_content.length()));
5668 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5669
5670 HttpRequestInfo request;
5671 request.method = "POST";
5672 request.url = GURL("http://www.google.com/upload");
5673 request.upload_data = new UploadData;
5674 request.load_flags = 0;
5675
5676 std::vector<UploadData::Element> elements;
5677 UploadData::Element element;
5678 element.SetToFilePath(temp_file);
5679 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535680 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365681
5682 MockRead data_reads[] = {
5683 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5684 MockRead(false, OK),
5685 };
5686 MockWrite data_writes[] = {
5687 MockWrite("POST /upload HTTP/1.1\r\n"
5688 "Host: www.google.com\r\n"
5689 "Connection: keep-alive\r\n"
5690 "Content-Length: 0\r\n\r\n"),
5691 MockWrite(false, OK),
5692 };
5693 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5694 arraysize(data_writes));
5695 session_deps.socket_factory.AddSocketDataProvider(&data);
5696
5697 TestCompletionCallback callback;
5698
[email protected]5a1d7ca2010-04-28 20:12:275699 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365700 EXPECT_EQ(ERR_IO_PENDING, rv);
5701
5702 rv = callback.WaitForResult();
5703 EXPECT_EQ(OK, rv);
5704
5705 const HttpResponseInfo* response = trans->GetResponseInfo();
5706 EXPECT_TRUE(response != NULL);
5707 EXPECT_TRUE(response->headers != NULL);
5708 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5709
5710 file_util::Delete(temp_file, false);
5711}
5712
5713TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
5714 SessionDependencies session_deps;
5715 scoped_ptr<HttpTransaction> trans(
5716 new HttpNetworkTransaction(CreateSession(&session_deps)));
5717
5718 FilePath temp_file;
5719 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5720 std::string temp_file_contents("Unreadable file.");
5721 std::string unreadable_contents(temp_file_contents.length(), '\0');
5722 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
5723 temp_file_contents.length()));
5724
5725 HttpRequestInfo request;
5726 request.method = "POST";
5727 request.url = GURL("http://www.google.com/upload");
5728 request.upload_data = new UploadData;
5729 request.load_flags = 0;
5730
5731 std::vector<UploadData::Element> elements;
5732 UploadData::Element element;
5733 element.SetToFilePath(temp_file);
5734 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535735 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365736
5737 MockRead data_reads[] = {
5738 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5739 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5740 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
5741
5742 MockRead("HTTP/1.1 200 OK\r\n"),
5743 MockRead("Content-Length: 0\r\n\r\n"),
5744 MockRead(false, OK),
5745 };
5746 MockWrite data_writes[] = {
5747 MockWrite("POST /upload HTTP/1.1\r\n"
5748 "Host: www.google.com\r\n"
5749 "Connection: keep-alive\r\n"
5750 "Content-Length: 16\r\n\r\n"),
5751 MockWrite(false, temp_file_contents.c_str()),
5752
5753 MockWrite("POST /upload HTTP/1.1\r\n"
5754 "Host: www.google.com\r\n"
5755 "Connection: keep-alive\r\n"
5756 "Content-Length: 16\r\n"
5757 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5758 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
5759 MockWrite(false, OK),
5760 };
5761 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5762 arraysize(data_writes));
5763 session_deps.socket_factory.AddSocketDataProvider(&data);
5764
5765 TestCompletionCallback callback1;
5766
[email protected]5a1d7ca2010-04-28 20:12:275767 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365768 EXPECT_EQ(ERR_IO_PENDING, rv);
5769
5770 rv = callback1.WaitForResult();
5771 EXPECT_EQ(OK, rv);
5772
5773 const HttpResponseInfo* response = trans->GetResponseInfo();
5774 EXPECT_TRUE(response != NULL);
5775 EXPECT_TRUE(response->headers != NULL);
5776 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
5777
5778 // The password prompt info should have been set in response->auth_challenge.
5779 EXPECT_TRUE(response->auth_challenge.get() != NULL);
5780 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5781 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5782 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5783
5784 // Now make the file unreadable and try again.
5785 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5786
5787 TestCompletionCallback callback2;
5788
[email protected]13c8a092010-07-29 06:15:445789 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:365790 EXPECT_EQ(ERR_IO_PENDING, rv);
5791
5792 rv = callback2.WaitForResult();
5793 EXPECT_EQ(OK, rv);
5794
5795 response = trans->GetResponseInfo();
5796 EXPECT_TRUE(response != NULL);
5797 EXPECT_TRUE(response->headers != NULL);
5798 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5799 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5800
5801 file_util::Delete(temp_file, false);
5802}
5803
[email protected]aeefc9e82010-02-19 16:18:275804// Tests that changes to Auth realms are treated like auth rejections.
5805TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
5806 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:275807
5808 HttpRequestInfo request;
5809 request.method = "GET";
5810 request.url = GURL("http://www.google.com/");
5811 request.load_flags = 0;
5812
5813 // First transaction will request a resource and receive a Basic challenge
5814 // with realm="first_realm".
5815 MockWrite data_writes1[] = {
5816 MockWrite("GET / HTTP/1.1\r\n"
5817 "Host: www.google.com\r\n"
5818 "Connection: keep-alive\r\n"
5819 "\r\n"),
5820 };
5821 MockRead data_reads1[] = {
5822 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5823 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5824 "\r\n"),
5825 };
5826
5827 // After calling trans->RestartWithAuth(), provide an Authentication header
5828 // for first_realm. The server will reject and provide a challenge with
5829 // second_realm.
5830 MockWrite data_writes2[] = {
5831 MockWrite("GET / HTTP/1.1\r\n"
5832 "Host: www.google.com\r\n"
5833 "Connection: keep-alive\r\n"
5834 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
5835 "\r\n"),
5836 };
5837 MockRead data_reads2[] = {
5838 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5839 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
5840 "\r\n"),
5841 };
5842
5843 // This again fails, and goes back to first_realm. Make sure that the
5844 // entry is removed from cache.
5845 MockWrite data_writes3[] = {
5846 MockWrite("GET / HTTP/1.1\r\n"
5847 "Host: www.google.com\r\n"
5848 "Connection: keep-alive\r\n"
5849 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
5850 "\r\n"),
5851 };
5852 MockRead data_reads3[] = {
5853 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5854 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5855 "\r\n"),
5856 };
5857
5858 // Try one last time (with the correct password) and get the resource.
5859 MockWrite data_writes4[] = {
5860 MockWrite("GET / HTTP/1.1\r\n"
5861 "Host: www.google.com\r\n"
5862 "Connection: keep-alive\r\n"
5863 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
5864 "\r\n"),
5865 };
5866 MockRead data_reads4[] = {
5867 MockRead("HTTP/1.1 200 OK\r\n"
5868 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:505869 "Content-Length: 5\r\n"
5870 "\r\n"
5871 "hello"),
[email protected]aeefc9e82010-02-19 16:18:275872 };
5873
5874 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5875 data_writes1, arraysize(data_writes1));
5876 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5877 data_writes2, arraysize(data_writes2));
5878 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5879 data_writes3, arraysize(data_writes3));
5880 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
5881 data_writes4, arraysize(data_writes4));
5882 session_deps.socket_factory.AddSocketDataProvider(&data1);
5883 session_deps.socket_factory.AddSocketDataProvider(&data2);
5884 session_deps.socket_factory.AddSocketDataProvider(&data3);
5885 session_deps.socket_factory.AddSocketDataProvider(&data4);
5886
5887 TestCompletionCallback callback1;
5888
[email protected]0b0bf032010-09-21 18:08:505889 scoped_ptr<HttpTransaction> trans(
5890 new HttpNetworkTransaction(CreateSession(&session_deps)));
5891
[email protected]aeefc9e82010-02-19 16:18:275892 // Issue the first request with Authorize headers. There should be a
5893 // password prompt for first_realm waiting to be filled in after the
5894 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:275895 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:275896 EXPECT_EQ(ERR_IO_PENDING, rv);
5897 rv = callback1.WaitForResult();
5898 EXPECT_EQ(OK, rv);
5899 const HttpResponseInfo* response = trans->GetResponseInfo();
5900 ASSERT_FALSE(response == NULL);
5901 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5902 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5903 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5904 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5905
5906 // Issue the second request with an incorrect password. There should be a
5907 // password prompt for second_realm waiting to be filled in after the
5908 // transaction completes.
5909 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:445910 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:275911 EXPECT_EQ(ERR_IO_PENDING, rv);
5912 rv = callback2.WaitForResult();
5913 EXPECT_EQ(OK, rv);
5914 response = trans->GetResponseInfo();
5915 ASSERT_FALSE(response == NULL);
5916 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5917 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5918 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
5919 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5920
5921 // Issue the third request with another incorrect password. There should be
5922 // a password prompt for first_realm waiting to be filled in. If the password
5923 // prompt is not present, it indicates that the HttpAuthCacheEntry for
5924 // first_realm was not correctly removed.
5925 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:445926 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:275927 EXPECT_EQ(ERR_IO_PENDING, rv);
5928 rv = callback3.WaitForResult();
5929 EXPECT_EQ(OK, rv);
5930 response = trans->GetResponseInfo();
5931 ASSERT_FALSE(response == NULL);
5932 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5933 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5934 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5935 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5936
5937 // Issue the fourth request with the correct password and username.
5938 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:445939 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:275940 EXPECT_EQ(ERR_IO_PENDING, rv);
5941 rv = callback4.WaitForResult();
5942 EXPECT_EQ(OK, rv);
5943 response = trans->GetResponseInfo();
5944 ASSERT_FALSE(response == NULL);
5945 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5946}
5947
[email protected]564b4912010-03-09 16:30:425948TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:385949 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
5950 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:425951
[email protected]564b4912010-03-09 16:30:425952 SessionDependencies session_deps;
5953
5954 MockRead data_reads[] = {
5955 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355956 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:425957 MockRead("hello world"),
5958 MockRead(false, OK),
5959 };
5960
5961 HttpRequestInfo request;
5962 request.method = "GET";
5963 request.url = GURL("http://www.google.com/");
5964 request.load_flags = 0;
5965
5966 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5967
5968 session_deps.socket_factory.AddSocketDataProvider(&data);
5969
5970 TestCompletionCallback callback;
5971
5972 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5973 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5974
[email protected]5a1d7ca2010-04-28 20:12:275975 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425976 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:535977
[email protected]2fbaecf22010-07-22 22:20:355978 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425979 const HttpAlternateProtocols& alternate_protocols =
5980 session->alternate_protocols();
5981 EXPECT_FALSE(
5982 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5983
5984 EXPECT_EQ(OK, callback.WaitForResult());
5985
5986 const HttpResponseInfo* response = trans->GetResponseInfo();
5987 ASSERT_TRUE(response != NULL);
5988 ASSERT_TRUE(response->headers != NULL);
5989 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535990 EXPECT_FALSE(response->was_fetched_via_spdy);
5991 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575992 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425993
5994 std::string response_data;
5995 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5996 EXPECT_EQ("hello world", response_data);
5997
5998 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5999 const HttpAlternateProtocols::PortProtocolPair alternate =
6000 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
6001 HttpAlternateProtocols::PortProtocolPair expected_alternate;
6002 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:356003 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426004 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426005
[email protected]8e6441ca2010-08-19 05:56:386006 HttpStreamFactory::set_use_alternate_protocols(false);
6007 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:426008}
6009
6010TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:386011 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426012 SessionDependencies session_deps;
6013
6014 HttpRequestInfo request;
6015 request.method = "GET";
6016 request.url = GURL("http://www.google.com/");
6017 request.load_flags = 0;
6018
6019 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6020 StaticSocketDataProvider first_data;
6021 first_data.set_connect_data(mock_connect);
6022 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6023
6024 MockRead data_reads[] = {
6025 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6026 MockRead("hello world"),
6027 MockRead(true, OK),
6028 };
6029 StaticSocketDataProvider second_data(
6030 data_reads, arraysize(data_reads), NULL, 0);
6031 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6032
6033 // TODO(willchan): Delete this extra data provider. It's necessary due to a
6034 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
6035 // http://crbug.com/37454.
6036 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6037
6038 TestCompletionCallback callback;
6039
6040 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6041
[email protected]2fbaecf22010-07-22 22:20:356042 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426043 HttpAlternateProtocols* alternate_protocols =
6044 session->mutable_alternate_protocols();
6045 alternate_protocols->SetAlternateProtocolFor(
6046 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:356047 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426048
6049 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6050
[email protected]5a1d7ca2010-04-28 20:12:276051 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426052 EXPECT_EQ(ERR_IO_PENDING, rv);
6053 EXPECT_EQ(OK, callback.WaitForResult());
6054
6055 const HttpResponseInfo* response = trans->GetResponseInfo();
6056 ASSERT_TRUE(response != NULL);
6057 ASSERT_TRUE(response->headers != NULL);
6058 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6059
6060 std::string response_data;
6061 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6062 EXPECT_EQ("hello world", response_data);
6063
6064 ASSERT_TRUE(
6065 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6066 const HttpAlternateProtocols::PortProtocolPair alternate =
6067 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6068 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386069 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426070}
6071
6072// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
6073// says that it does SPDY, but it just does the TLS handshake, but the NPN
6074// response does not indicate SPDY, so we just do standard HTTPS over the port.
6075// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
6076// on the original port.
[email protected]a2cb8122010-03-10 17:22:426077// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
6078// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:536079//
[email protected]a2cb8122010-03-10 17:22:426080// HttpRequestInfo request;
6081// request.method = "GET";
6082// request.url = GURL("http://www.google.com/");
6083// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:536084//
[email protected]a2cb8122010-03-10 17:22:426085// MockRead data_reads[] = {
6086// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6087// MockRead("hello world"),
6088// MockRead(true, OK),
6089// };
6090// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6091// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:536092//
[email protected]a2cb8122010-03-10 17:22:426093// SSLSocketDataProvider ssl(true, OK);
6094// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:536095//
[email protected]a2cb8122010-03-10 17:22:426096// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:536097//
[email protected]a2cb8122010-03-10 17:22:426098// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:536099//
[email protected]a2cb8122010-03-10 17:22:426100// HostPortPair http_host_port_pair;
6101// http_host_port_pair.host = "www.google.com";
6102// http_host_port_pair.port = 80;
6103// HttpAlternateProtocols* alternate_protocols =
6104// session->mutable_alternate_protocols();
6105// alternate_protocols->SetAlternateProtocolFor(
6106// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:066107// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:536108//
[email protected]a2cb8122010-03-10 17:22:426109// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:536110//
[email protected]5a1d7ca2010-04-28 20:12:276111// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:426112// EXPECT_EQ(ERR_IO_PENDING, rv);
6113// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:536114//
[email protected]a2cb8122010-03-10 17:22:426115// const HttpResponseInfo* response = trans->GetResponseInfo();
6116// ASSERT_TRUE(response != NULL);
6117// ASSERT_TRUE(response->headers != NULL);
6118// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:536119//
[email protected]a2cb8122010-03-10 17:22:426120// std::string response_data;
6121// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6122// EXPECT_EQ("hello world", response_data);
6123// }
6124
6125TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386126 HttpStreamFactory::set_use_alternate_protocols(true);
6127 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:426128 SessionDependencies session_deps;
6129
6130 HttpRequestInfo request;
6131 request.method = "GET";
6132 request.url = GURL("http://www.google.com/");
6133 request.load_flags = 0;
6134
[email protected]a2cb8122010-03-10 17:22:426135 StaticSocketDataProvider first_tcp_connect;
6136 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
6137
6138 SSLSocketDataProvider ssl(true, OK);
6139 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6140
[email protected]564b4912010-03-09 16:30:426141 MockRead data_reads[] = {
6142 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6143 MockRead("hello world"),
6144 MockRead(true, OK),
6145 };
[email protected]a2cb8122010-03-10 17:22:426146 StaticSocketDataProvider fallback_data(
6147 data_reads, arraysize(data_reads), NULL, 0);
6148 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:426149
6150 TestCompletionCallback callback;
6151
6152 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6153
[email protected]2fbaecf22010-07-22 22:20:356154 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426155 HttpAlternateProtocols* alternate_protocols =
6156 session->mutable_alternate_protocols();
6157 alternate_protocols->SetAlternateProtocolFor(
6158 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:356159 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426160
6161 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6162
[email protected]5a1d7ca2010-04-28 20:12:276163 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426164 EXPECT_EQ(ERR_IO_PENDING, rv);
6165 EXPECT_EQ(OK, callback.WaitForResult());
6166
6167 const HttpResponseInfo* response = trans->GetResponseInfo();
6168 ASSERT_TRUE(response != NULL);
6169 ASSERT_TRUE(response->headers != NULL);
6170 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6171
6172 std::string response_data;
6173 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6174 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:386175 HttpStreamFactory::set_next_protos("");
6176 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546177}
6178
6179TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386180 HttpStreamFactory::set_use_alternate_protocols(true);
6181 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546182 SessionDependencies session_deps;
6183
6184 HttpRequestInfo request;
6185 request.method = "GET";
6186 request.url = GURL("http://www.google.com/");
6187 request.load_flags = 0;
6188
6189 MockRead data_reads[] = {
6190 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356191 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546192 MockRead("hello world"),
6193 MockRead(true, OK),
6194 };
6195
6196 StaticSocketDataProvider first_transaction(
6197 data_reads, arraysize(data_reads), NULL, 0);
6198 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6199
6200 SSLSocketDataProvider ssl(true, OK);
6201 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356202 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536203 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546204 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6205
[email protected]2bd93022010-07-17 00:58:446206 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136207 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546208
[email protected]2bd93022010-07-17 00:58:446209 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6210 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546211 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136212 CreateMockRead(*resp),
6213 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546214 MockRead(true, 0, 0),
6215 };
6216
6217 scoped_refptr<DelayedSocketData> spdy_data(
6218 new DelayedSocketData(
6219 1, // wait for one write to finish before reading.
6220 spdy_reads, arraysize(spdy_reads),
6221 spdy_writes, arraysize(spdy_writes)));
6222 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6223
6224 TestCompletionCallback callback;
6225
6226 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6227 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6228
[email protected]5a1d7ca2010-04-28 20:12:276229 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546230 EXPECT_EQ(ERR_IO_PENDING, rv);
6231 EXPECT_EQ(OK, callback.WaitForResult());
6232
6233 const HttpResponseInfo* response = trans->GetResponseInfo();
6234 ASSERT_TRUE(response != NULL);
6235 ASSERT_TRUE(response->headers != NULL);
6236 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6237
6238 std::string response_data;
6239 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6240 EXPECT_EQ("hello world", response_data);
6241
6242 trans.reset(new HttpNetworkTransaction(session));
6243
[email protected]5a1d7ca2010-04-28 20:12:276244 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546245 EXPECT_EQ(ERR_IO_PENDING, rv);
6246 EXPECT_EQ(OK, callback.WaitForResult());
6247
6248 response = trans->GetResponseInfo();
6249 ASSERT_TRUE(response != NULL);
6250 ASSERT_TRUE(response->headers != NULL);
6251 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536252 EXPECT_TRUE(response->was_fetched_via_spdy);
6253 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576254 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546255
6256 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6257 EXPECT_EQ("hello!", response_data);
6258
[email protected]8e6441ca2010-08-19 05:56:386259 HttpStreamFactory::set_next_protos("");
6260 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546261}
6262
[email protected]631f1322010-04-30 17:59:116263class CapturingProxyResolver : public ProxyResolver {
6264 public:
6265 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6266 virtual ~CapturingProxyResolver() {}
6267
6268 virtual int GetProxyForURL(const GURL& url,
6269 ProxyInfo* results,
6270 CompletionCallback* callback,
6271 RequestHandle* request,
6272 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406273 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6274 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426275 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116276 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426277 return OK;
[email protected]631f1322010-04-30 17:59:116278 }
6279
6280 virtual void CancelRequest(RequestHandle request) {
6281 NOTREACHED();
6282 }
6283
[email protected]24476402010-07-20 20:55:176284 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116285 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426286 return OK;
[email protected]631f1322010-04-30 17:59:116287 }
6288
[email protected]24476402010-07-20 20:55:176289 const std::vector<GURL>& resolved() const { return resolved_; }
6290
6291 private:
[email protected]631f1322010-04-30 17:59:116292 std::vector<GURL> resolved_;
6293
6294 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6295};
6296
[email protected]631f1322010-04-30 17:59:116297TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386298 HttpStreamFactory::set_use_alternate_protocols(true);
6299 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116300
6301 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426302 proxy_config.set_auto_detect(true);
6303 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116304
[email protected]631f1322010-04-30 17:59:116305 CapturingProxyResolver* capturing_proxy_resolver =
6306 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386307 SessionDependencies session_deps(new ProxyService(
6308 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6309 NULL));
[email protected]631f1322010-04-30 17:59:116310
6311 HttpRequestInfo request;
6312 request.method = "GET";
6313 request.url = GURL("http://www.google.com/");
6314 request.load_flags = 0;
6315
6316 MockRead data_reads[] = {
6317 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356318 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116319 MockRead("hello world"),
6320 MockRead(true, OK),
6321 };
6322
6323 StaticSocketDataProvider first_transaction(
6324 data_reads, arraysize(data_reads), NULL, 0);
6325 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6326
6327 SSLSocketDataProvider ssl(true, OK);
6328 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356329 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536330 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116331 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6332
[email protected]2bd93022010-07-17 00:58:446333 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116334 MockWrite spdy_writes[] = {
6335 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6336 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426337 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136338 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116339 };
6340
[email protected]d911f1b2010-05-05 22:39:426341 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6342
[email protected]2bd93022010-07-17 00:58:446343 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6344 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116345 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426346 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136347 CreateMockRead(*resp.get(), 4), // 2, 4
6348 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426349 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116350 };
6351
[email protected]d911f1b2010-05-05 22:39:426352 scoped_refptr<OrderedSocketData> spdy_data(
6353 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116354 spdy_reads, arraysize(spdy_reads),
6355 spdy_writes, arraysize(spdy_writes)));
6356 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6357
6358 TestCompletionCallback callback;
6359
6360 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6361 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6362
6363 int rv = trans->Start(&request, &callback, BoundNetLog());
6364 EXPECT_EQ(ERR_IO_PENDING, rv);
6365 EXPECT_EQ(OK, callback.WaitForResult());
6366
6367 const HttpResponseInfo* response = trans->GetResponseInfo();
6368 ASSERT_TRUE(response != NULL);
6369 ASSERT_TRUE(response->headers != NULL);
6370 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536371 EXPECT_FALSE(response->was_fetched_via_spdy);
6372 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116373
6374 std::string response_data;
6375 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6376 EXPECT_EQ("hello world", response_data);
6377
6378 trans.reset(new HttpNetworkTransaction(session));
6379
6380 rv = trans->Start(&request, &callback, BoundNetLog());
6381 EXPECT_EQ(ERR_IO_PENDING, rv);
6382 EXPECT_EQ(OK, callback.WaitForResult());
6383
6384 response = trans->GetResponseInfo();
6385 ASSERT_TRUE(response != NULL);
6386 ASSERT_TRUE(response->headers != NULL);
6387 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536388 EXPECT_TRUE(response->was_fetched_via_spdy);
6389 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116390
6391 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6392 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:426393 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
6394 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116395 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426396 EXPECT_EQ("https://www.google.com/",
6397 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116398
[email protected]8e6441ca2010-08-19 05:56:386399 HttpStreamFactory::set_next_protos("");
6400 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116401}
[email protected]631f1322010-04-30 17:59:116402
[email protected]2ff8b312010-04-26 22:20:546403TEST_F(HttpNetworkTransactionTest,
6404 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386405 HttpStreamFactory::set_use_alternate_protocols(true);
6406 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546407 SessionDependencies session_deps;
6408
6409 HttpRequestInfo request;
6410 request.method = "GET";
6411 request.url = GURL("http://www.google.com/");
6412 request.load_flags = 0;
6413
6414 MockRead data_reads[] = {
6415 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356416 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546417 MockRead("hello world"),
6418 MockRead(true, OK),
6419 };
6420
6421 StaticSocketDataProvider first_transaction(
6422 data_reads, arraysize(data_reads), NULL, 0);
6423 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6424
6425 SSLSocketDataProvider ssl(true, OK);
6426 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356427 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536428 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546429 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:536430 // Make sure we use ssl for spdy here.
6431 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:546432
[email protected]2bd93022010-07-17 00:58:446433 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136434 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546435
[email protected]2bd93022010-07-17 00:58:446436 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6437 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546438 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136439 CreateMockRead(*resp),
6440 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546441 MockRead(true, 0, 0),
6442 };
6443
6444 scoped_refptr<DelayedSocketData> spdy_data(
6445 new DelayedSocketData(
6446 1, // wait for one write to finish before reading.
6447 spdy_reads, arraysize(spdy_reads),
6448 spdy_writes, arraysize(spdy_writes)));
6449 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6450
6451 TestCompletionCallback callback;
6452
6453 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6454
6455 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6456
[email protected]5a1d7ca2010-04-28 20:12:276457 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546458 EXPECT_EQ(ERR_IO_PENDING, rv);
6459 EXPECT_EQ(OK, callback.WaitForResult());
6460
6461 const HttpResponseInfo* response = trans->GetResponseInfo();
6462 ASSERT_TRUE(response != NULL);
6463 ASSERT_TRUE(response->headers != NULL);
6464 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6465
6466 std::string response_data;
6467 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6468 EXPECT_EQ("hello world", response_data);
6469
6470 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:386471 HostPortPair host_port_pair("www.google.com", 443);
6472 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:546473 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:276474 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
6475 BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:276476 scoped_refptr<TCPSocketParams> tcp_params(
6477 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:386478
6479 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
6480 EXPECT_EQ(ERR_IO_PENDING,
6481 connection->Init(host_port_pair.ToString(),tcp_params, LOWEST,
6482 &callback, session->tcp_socket_pool(),
6483 BoundNetLog()));
6484 EXPECT_EQ(OK, callback.WaitForResult());
6485
6486 SSLConfig ssl_config;
6487 session->ssl_config_service()->GetSSLConfig(&ssl_config);
6488 ClientSocket* socket = connection->release_socket();
[email protected]7ab5bbd12010-10-19 13:33:216489 socket = session->socket_factory()->CreateSSLClientSocket(
6490 socket, "" , ssl_config, NULL /* ssl_host_info */);
[email protected]02b0c342010-09-25 21:09:386491 connection->set_socket(socket);
6492 EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
6493 EXPECT_EQ(OK, callback.WaitForResult());
6494
6495 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(connection.release(),
6496 true, OK));
6497
[email protected]2ff8b312010-04-26 22:20:546498 trans.reset(new HttpNetworkTransaction(session));
6499
[email protected]5a1d7ca2010-04-28 20:12:276500 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546501 EXPECT_EQ(ERR_IO_PENDING, rv);
6502 EXPECT_EQ(OK, callback.WaitForResult());
6503
6504 response = trans->GetResponseInfo();
6505 ASSERT_TRUE(response != NULL);
6506 ASSERT_TRUE(response->headers != NULL);
6507 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536508 EXPECT_TRUE(response->was_fetched_via_spdy);
6509 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576510 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546511
6512 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6513 EXPECT_EQ("hello!", response_data);
6514
[email protected]8e6441ca2010-08-19 05:56:386515 HttpStreamFactory::set_next_protos("");
6516 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426517}
6518
[email protected]044de0642010-06-17 10:42:156519// GenerateAuthToken is a mighty big test.
6520// It tests all permutation of GenerateAuthToken behavior:
6521// - Synchronous and Asynchronous completion.
6522// - OK or error on completion.
6523// - Direct connection, non-authenticating proxy, and authenticating proxy.
6524// - HTTP or HTTPS backend (to include proxy tunneling).
6525// - Non-authenticating and authenticating backend.
6526//
6527// In all, there are 44 reasonable permuations (for example, if there are
6528// problems generating an auth token for an authenticating proxy, we don't
6529// need to test all permutations of the backend server).
6530//
6531// The test proceeds by going over each of the configuration cases, and
6532// potentially running up to three rounds in each of the tests. The TestConfig
6533// specifies both the configuration for the test as well as the expectations
6534// for the results.
6535TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:506536 static const char kServer[] = "http://www.example.com";
6537 static const char kSecureServer[] = "https://www.example.com";
6538 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:156539 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
6540
6541 enum AuthTiming {
6542 AUTH_NONE,
6543 AUTH_SYNC,
6544 AUTH_ASYNC,
6545 };
6546
6547 const MockWrite kGet(
6548 "GET / HTTP/1.1\r\n"
6549 "Host: www.example.com\r\n"
6550 "Connection: keep-alive\r\n\r\n");
6551 const MockWrite kGetProxy(
6552 "GET http://www.example.com/ HTTP/1.1\r\n"
6553 "Host: www.example.com\r\n"
6554 "Proxy-Connection: keep-alive\r\n\r\n");
6555 const MockWrite kGetAuth(
6556 "GET / HTTP/1.1\r\n"
6557 "Host: www.example.com\r\n"
6558 "Connection: keep-alive\r\n"
6559 "Authorization: auth_token\r\n\r\n");
6560 const MockWrite kGetProxyAuth(
6561 "GET http://www.example.com/ HTTP/1.1\r\n"
6562 "Host: www.example.com\r\n"
6563 "Proxy-Connection: keep-alive\r\n"
6564 "Proxy-Authorization: auth_token\r\n\r\n");
6565 const MockWrite kGetAuthThroughProxy(
6566 "GET http://www.example.com/ HTTP/1.1\r\n"
6567 "Host: www.example.com\r\n"
6568 "Proxy-Connection: keep-alive\r\n"
6569 "Authorization: auth_token\r\n\r\n");
6570 const MockWrite kGetAuthWithProxyAuth(
6571 "GET http://www.example.com/ HTTP/1.1\r\n"
6572 "Host: www.example.com\r\n"
6573 "Proxy-Connection: keep-alive\r\n"
6574 "Proxy-Authorization: auth_token\r\n"
6575 "Authorization: auth_token\r\n\r\n");
6576 const MockWrite kConnect(
6577 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6578 "Host: www.example.com\r\n"
6579 "Proxy-Connection: keep-alive\r\n\r\n");
6580 const MockWrite kConnectProxyAuth(
6581 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6582 "Host: www.example.com\r\n"
6583 "Proxy-Connection: keep-alive\r\n"
6584 "Proxy-Authorization: auth_token\r\n\r\n");
6585
6586 const MockRead kSuccess(
6587 "HTTP/1.1 200 OK\r\n"
6588 "Content-Type: text/html; charset=iso-8859-1\r\n"
6589 "Content-Length: 3\r\n\r\n"
6590 "Yes");
6591 const MockRead kFailure(
6592 "Should not be called.");
6593 const MockRead kServerChallenge(
6594 "HTTP/1.1 401 Unauthorized\r\n"
6595 "WWW-Authenticate: Mock realm=server\r\n"
6596 "Content-Type: text/html; charset=iso-8859-1\r\n"
6597 "Content-Length: 14\r\n\r\n"
6598 "Unauthorized\r\n");
6599 const MockRead kProxyChallenge(
6600 "HTTP/1.1 407 Unauthorized\r\n"
6601 "Proxy-Authenticate: Mock realm=proxy\r\n"
6602 "Proxy-Connection: close\r\n"
6603 "Content-Type: text/html; charset=iso-8859-1\r\n"
6604 "Content-Length: 14\r\n\r\n"
6605 "Unauthorized\r\n");
6606 const MockRead kProxyConnected(
6607 "HTTP/1.1 200 Connection Established\r\n\r\n");
6608
6609 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
6610 // no constructors, but the C++ compiler on Windows warns about
6611 // unspecified data in compound literals. So, moved to using constructors,
6612 // and TestRound's created with the default constructor should not be used.
6613 struct TestRound {
6614 TestRound()
6615 : expected_rv(ERR_UNEXPECTED),
6616 extra_write(NULL),
6617 extra_read(NULL) {
6618 }
6619 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6620 int expected_rv_arg)
6621 : write(write_arg),
6622 read(read_arg),
6623 expected_rv(expected_rv_arg),
6624 extra_write(NULL),
6625 extra_read(NULL) {
6626 }
6627 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6628 int expected_rv_arg, const MockWrite* extra_write_arg,
6629 const MockWrite* extra_read_arg)
6630 : write(write_arg),
6631 read(read_arg),
6632 expected_rv(expected_rv_arg),
6633 extra_write(extra_write_arg),
6634 extra_read(extra_read_arg) {
6635 }
6636 MockWrite write;
6637 MockRead read;
6638 int expected_rv;
6639 const MockWrite* extra_write;
6640 const MockRead* extra_read;
6641 };
6642
6643 static const int kNoSSL = 500;
6644
6645 struct TestConfig {
6646 const char* proxy_url;
6647 AuthTiming proxy_auth_timing;
6648 int proxy_auth_rv;
6649 const char* server_url;
6650 AuthTiming server_auth_timing;
6651 int server_auth_rv;
6652 int num_auth_rounds;
6653 int first_ssl_round;
6654 TestRound rounds[3];
6655 } test_configs[] = {
6656 // Non-authenticating HTTP server with a direct connection.
6657 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6658 { TestRound(kGet, kSuccess, OK)}},
6659 // Authenticating HTTP server with a direct connection.
6660 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6661 { TestRound(kGet, kServerChallenge, OK),
6662 TestRound(kGetAuth, kSuccess, OK)}},
6663 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6664 { TestRound(kGet, kServerChallenge, OK),
6665 TestRound(kGetAuth, kFailure, kAuthErr)}},
6666 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6667 { TestRound(kGet, kServerChallenge, OK),
6668 TestRound(kGetAuth, kSuccess, OK)}},
6669 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6670 { TestRound(kGet, kServerChallenge, OK),
6671 TestRound(kGetAuth, kFailure, kAuthErr)}},
6672 // Non-authenticating HTTP server through a non-authenticating proxy.
6673 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6674 { TestRound(kGetProxy, kSuccess, OK)}},
6675 // Authenticating HTTP server through a non-authenticating proxy.
6676 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6677 { TestRound(kGetProxy, kServerChallenge, OK),
6678 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6679 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6680 { TestRound(kGetProxy, kServerChallenge, OK),
6681 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6682 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6683 { TestRound(kGetProxy, kServerChallenge, OK),
6684 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6685 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6686 { TestRound(kGetProxy, kServerChallenge, OK),
6687 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6688 // Non-authenticating HTTP server through an authenticating proxy.
6689 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6690 { TestRound(kGetProxy, kProxyChallenge, OK),
6691 TestRound(kGetProxyAuth, kSuccess, OK)}},
6692 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6693 { TestRound(kGetProxy, kProxyChallenge, OK),
6694 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6695 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6696 { TestRound(kGetProxy, kProxyChallenge, OK),
6697 TestRound(kGetProxyAuth, kSuccess, OK)}},
6698 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6699 { TestRound(kGetProxy, kProxyChallenge, OK),
6700 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6701 // Authenticating HTTP server through an authenticating proxy.
6702 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6703 { TestRound(kGetProxy, kProxyChallenge, OK),
6704 TestRound(kGetProxyAuth, kServerChallenge, OK),
6705 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6706 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6707 { TestRound(kGetProxy, kProxyChallenge, OK),
6708 TestRound(kGetProxyAuth, kServerChallenge, OK),
6709 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6710 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6711 { TestRound(kGetProxy, kProxyChallenge, OK),
6712 TestRound(kGetProxyAuth, kServerChallenge, OK),
6713 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6714 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6715 { TestRound(kGetProxy, kProxyChallenge, OK),
6716 TestRound(kGetProxyAuth, kServerChallenge, OK),
6717 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6718 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6719 { TestRound(kGetProxy, kProxyChallenge, OK),
6720 TestRound(kGetProxyAuth, kServerChallenge, OK),
6721 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6722 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6723 { TestRound(kGetProxy, kProxyChallenge, OK),
6724 TestRound(kGetProxyAuth, kServerChallenge, OK),
6725 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6726 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6727 { TestRound(kGetProxy, kProxyChallenge, OK),
6728 TestRound(kGetProxyAuth, kServerChallenge, OK),
6729 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6730 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6731 { TestRound(kGetProxy, kProxyChallenge, OK),
6732 TestRound(kGetProxyAuth, kServerChallenge, OK),
6733 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6734 // Non-authenticating HTTPS server with a direct connection.
6735 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6736 { TestRound(kGet, kSuccess, OK)}},
6737 // Authenticating HTTPS server with a direct connection.
6738 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6739 { TestRound(kGet, kServerChallenge, OK),
6740 TestRound(kGetAuth, kSuccess, OK)}},
6741 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6742 { TestRound(kGet, kServerChallenge, OK),
6743 TestRound(kGetAuth, kFailure, kAuthErr)}},
6744 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6745 { TestRound(kGet, kServerChallenge, OK),
6746 TestRound(kGetAuth, kSuccess, OK)}},
6747 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6748 { TestRound(kGet, kServerChallenge, OK),
6749 TestRound(kGetAuth, kFailure, kAuthErr)}},
6750 // Non-authenticating HTTPS server with a non-authenticating proxy.
6751 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6752 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
6753 // Authenticating HTTPS server through a non-authenticating proxy.
6754 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6755 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6756 TestRound(kGetAuth, kSuccess, OK)}},
6757 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6758 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6759 TestRound(kGetAuth, kFailure, kAuthErr)}},
6760 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6761 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6762 TestRound(kGetAuth, kSuccess, OK)}},
6763 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6764 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6765 TestRound(kGetAuth, kFailure, kAuthErr)}},
6766 // Non-Authenticating HTTPS server through an authenticating proxy.
6767 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6768 { TestRound(kConnect, kProxyChallenge, OK),
6769 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6770 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6771 { TestRound(kConnect, kProxyChallenge, OK),
6772 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6773 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6774 { TestRound(kConnect, kProxyChallenge, OK),
6775 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6776 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6777 { TestRound(kConnect, kProxyChallenge, OK),
6778 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6779 // Authenticating HTTPS server through an authenticating proxy.
6780 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6781 { TestRound(kConnect, kProxyChallenge, OK),
6782 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6783 &kGet, &kServerChallenge),
6784 TestRound(kGetAuth, kSuccess, OK)}},
6785 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6786 { TestRound(kConnect, kProxyChallenge, OK),
6787 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6788 &kGet, &kServerChallenge),
6789 TestRound(kGetAuth, kFailure, kAuthErr)}},
6790 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6791 { TestRound(kConnect, kProxyChallenge, OK),
6792 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6793 &kGet, &kServerChallenge),
6794 TestRound(kGetAuth, kSuccess, OK)}},
6795 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6796 { TestRound(kConnect, kProxyChallenge, OK),
6797 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6798 &kGet, &kServerChallenge),
6799 TestRound(kGetAuth, kFailure, kAuthErr)}},
6800 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6801 { TestRound(kConnect, kProxyChallenge, OK),
6802 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6803 &kGet, &kServerChallenge),
6804 TestRound(kGetAuth, kSuccess, OK)}},
6805 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6806 { TestRound(kConnect, kProxyChallenge, OK),
6807 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6808 &kGet, &kServerChallenge),
6809 TestRound(kGetAuth, kFailure, kAuthErr)}},
6810 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6811 { TestRound(kConnect, kProxyChallenge, OK),
6812 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6813 &kGet, &kServerChallenge),
6814 TestRound(kGetAuth, kSuccess, OK)}},
6815 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6816 { TestRound(kConnect, kProxyChallenge, OK),
6817 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6818 &kGet, &kServerChallenge),
6819 TestRound(kGetAuth, kFailure, kAuthErr)}},
6820 };
6821
6822 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:006823 HttpAuthHandlerMock::Factory* auth_factory(
6824 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:156825 session_deps.http_auth_handler_factory.reset(auth_factory);
6826
6827 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
6828 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:266829
6830 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:156831 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006832 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156833 std::string auth_challenge = "Mock realm=proxy";
6834 GURL origin(test_config.proxy_url);
6835 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6836 auth_challenge.end());
6837 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
6838 origin, BoundNetLog());
6839 auth_handler->SetGenerateExpectation(
6840 test_config.proxy_auth_timing == AUTH_ASYNC,
6841 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:156842 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6843 }
6844 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006845 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156846 std::string auth_challenge = "Mock realm=server";
6847 GURL origin(test_config.server_url);
6848 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6849 auth_challenge.end());
6850 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6851 origin, BoundNetLog());
6852 auth_handler->SetGenerateExpectation(
6853 test_config.server_auth_timing == AUTH_ASYNC,
6854 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:156855 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6856 }
6857 if (test_config.proxy_url) {
6858 session_deps.proxy_service =
[email protected]81cdfcd2010-10-16 00:49:006859 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:156860 } else {
[email protected]ebeefff32010-09-15 05:10:026861 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:156862 }
6863
6864 HttpRequestInfo request;
6865 request.method = "GET";
6866 request.url = GURL(test_config.server_url);
6867 request.load_flags = 0;
6868
[email protected]0b0bf032010-09-21 18:08:506869 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6870 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:156871
6872 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
6873 const TestRound& read_write_round = test_config.rounds[round];
6874
6875 // Set up expected reads and writes.
6876 MockRead reads[2];
6877 reads[0] = read_write_round.read;
6878 size_t length_reads = 1;
6879 if (read_write_round.extra_read) {
6880 reads[1] = *read_write_round.extra_read;
6881 length_reads = 2;
6882 }
6883
6884 MockWrite writes[2];
6885 writes[0] = read_write_round.write;
6886 size_t length_writes = 1;
6887 if (read_write_round.extra_write) {
6888 writes[1] = *read_write_round.extra_write;
6889 length_writes = 2;
6890 }
6891 StaticSocketDataProvider data_provider(
6892 reads, length_reads, writes, length_writes);
6893 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6894
6895 // Add an SSL sequence if necessary.
6896 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
6897 if (round >= test_config.first_ssl_round)
6898 session_deps.socket_factory.AddSSLSocketDataProvider(
6899 &ssl_socket_data_provider);
6900
6901 // Start or restart the transaction.
6902 TestCompletionCallback callback;
6903 int rv;
6904 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:506905 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:156906 } else {
[email protected]0b0bf032010-09-21 18:08:506907 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:156908 }
6909 if (rv == ERR_IO_PENDING)
6910 rv = callback.WaitForResult();
6911
6912 // Compare results with expected data.
6913 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:506914 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:156915 if (read_write_round.expected_rv == OK) {
6916 EXPECT_FALSE(response == NULL);
6917 } else {
6918 EXPECT_TRUE(response == NULL);
6919 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6920 continue;
6921 }
6922 if (round + 1 < test_config.num_auth_rounds) {
6923 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6924 } else {
6925 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6926 }
6927 }
[email protected]e5ae96a2010-04-14 20:12:456928 }
6929}
6930
[email protected]c871bce92010-07-15 21:51:146931TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
6932 // Do multi-round authentication and make sure it works correctly.
6933 SessionDependencies session_deps;
6934 HttpAuthHandlerMock::Factory* auth_factory(
6935 new HttpAuthHandlerMock::Factory());
6936 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]ebeefff32010-09-15 05:10:026937 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]c871bce92010-07-15 21:51:146938 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
6939 session_deps.host_resolver->set_synchronous_mode(true);
6940
6941 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
6942 auth_handler->set_connection_based(true);
6943 std::string auth_challenge = "Mock realm=server";
6944 GURL origin("http://www.example.com");
6945 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6946 auth_challenge.end());
6947 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6948 origin, BoundNetLog());
6949 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6950
[email protected]ad8e04a2010-11-01 04:16:276951 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c871bce92010-07-15 21:51:146952 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6953
6954 int rv = OK;
6955 const HttpResponseInfo* response = NULL;
6956 HttpRequestInfo request;
6957 request.method = "GET";
6958 request.url = origin;
6959 request.load_flags = 0;
6960 TestCompletionCallback callback;
6961
6962 const MockWrite kGet(
6963 "GET / HTTP/1.1\r\n"
6964 "Host: www.example.com\r\n"
6965 "Connection: keep-alive\r\n\r\n");
6966 const MockWrite kGetAuth(
6967 "GET / HTTP/1.1\r\n"
6968 "Host: www.example.com\r\n"
6969 "Connection: keep-alive\r\n"
6970 "Authorization: auth_token\r\n\r\n");
6971
6972 const MockRead kServerChallenge(
6973 "HTTP/1.1 401 Unauthorized\r\n"
6974 "WWW-Authenticate: Mock realm=server\r\n"
6975 "Content-Type: text/html; charset=iso-8859-1\r\n"
6976 "Content-Length: 14\r\n\r\n"
6977 "Unauthorized\r\n");
6978 const MockRead kSuccess(
6979 "HTTP/1.1 200 OK\r\n"
6980 "Content-Type: text/html; charset=iso-8859-1\r\n"
6981 "Content-Length: 3\r\n\r\n"
6982 "Yes");
6983
6984 MockWrite writes[] = {
6985 // First round
6986 kGet,
6987 // Second round
6988 kGetAuth,
6989 // Third round
6990 kGetAuth,
[email protected]eca50e122010-09-11 14:03:306991 // Fourth round
6992 kGetAuth
[email protected]c871bce92010-07-15 21:51:146993 };
6994 MockRead reads[] = {
6995 // First round
6996 kServerChallenge,
6997 // Second round
6998 kServerChallenge,
6999 // Third round
[email protected]eca50e122010-09-11 14:03:307000 kServerChallenge,
7001 // Fourth round
[email protected]c871bce92010-07-15 21:51:147002 kSuccess,
7003 };
7004 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7005 writes, arraysize(writes));
7006 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7007
7008 // First round
7009 auth_handler->SetGenerateExpectation(false, OK);
7010 rv = trans->Start(&request, &callback, BoundNetLog());
7011 if (rv == ERR_IO_PENDING)
7012 rv = callback.WaitForResult();
7013 EXPECT_EQ(OK, rv);
7014 response = trans->GetResponseInfo();
7015 ASSERT_FALSE(response == NULL);
7016 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7017
7018 // Second round
7019 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447020 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:147021 if (rv == ERR_IO_PENDING)
7022 rv = callback.WaitForResult();
7023 EXPECT_EQ(OK, rv);
7024 response = trans->GetResponseInfo();
7025 ASSERT_FALSE(response == NULL);
7026 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7027
7028 // Third round
7029 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447030 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:147031 if (rv == ERR_IO_PENDING)
7032 rv = callback.WaitForResult();
7033 EXPECT_EQ(OK, rv);
7034 response = trans->GetResponseInfo();
7035 ASSERT_FALSE(response == NULL);
7036 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]eca50e122010-09-11 14:03:307037
7038 // Fourth round
7039 auth_handler->SetGenerateExpectation(false, OK);
7040 rv = trans->RestartWithAuth(string16(), string16(), &callback);
7041 if (rv == ERR_IO_PENDING)
7042 rv = callback.WaitForResult();
7043 EXPECT_EQ(OK, rv);
7044 response = trans->GetResponseInfo();
7045 ASSERT_FALSE(response == NULL);
7046 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]c871bce92010-07-15 21:51:147047}
7048
[email protected]aeaca1f2010-04-20 22:05:217049class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7050 public:
[email protected]06650c52010-06-03 00:49:177051 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217052 : fail_all_(fail_all) {
7053 }
7054
7055 virtual MockRead GetNextRead() {
7056 if (fail_all_)
7057 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7058
7059 return MockRead(false /* async */,
7060 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7061 }
7062
7063 virtual MockWriteResult OnWrite(const std::string& data) {
7064 return MockWriteResult(false /* async */, data.size());
7065 }
7066
7067 void Reset() {
7068 }
7069
7070 private:
7071 const bool fail_all_;
7072};
7073
7074// Test that we restart a connection when we see a decompression failure from
7075// the peer during the handshake. (In the real world we'll restart with SSLv3
7076// and we won't offer DEFLATE in that case.)
7077TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7078 HttpRequestInfo request;
7079 request.method = "GET";
7080 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7081 request.load_flags = 0;
7082
7083 SessionDependencies session_deps;
7084 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7085 false /* fail all reads */);
7086 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7087 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117088 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217089 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7090 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7091 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7092 session_deps.socket_factory.AddSSLSocketDataProvider(
7093 &ssl_socket_data_provider1);
7094 session_deps.socket_factory.AddSSLSocketDataProvider(
7095 &ssl_socket_data_provider2);
7096
[email protected]e60e47a2010-07-14 03:37:187097 // Work around http://crbug.com/37454
7098 StaticSocketDataProvider bug37454_connection;
7099 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7100 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7101
[email protected]aeaca1f2010-04-20 22:05:217102 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7103 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7104 TestCompletionCallback callback;
7105
[email protected]5a1d7ca2010-04-28 20:12:277106 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217107 EXPECT_EQ(ERR_IO_PENDING, rv);
7108 EXPECT_EQ(OK, callback.WaitForResult());
7109
7110 const HttpResponseInfo* response = trans->GetResponseInfo();
7111 ASSERT_TRUE(response != NULL);
7112 ASSERT_TRUE(response->headers != NULL);
7113 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7114
7115 std::string response_data;
7116 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7117 EXPECT_EQ("ok.", response_data);
7118}
7119
7120// Test that we restart a connection if we get a decompression failure from the
7121// peer while reading the first bytes from the connection. This occurs when the
7122// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7123// in the handshake.
7124TEST_F(HttpNetworkTransactionTest,
7125 RestartAfterTLSDecompressionFailureWithFalseStart) {
7126 HttpRequestInfo request;
7127 request.method = "GET";
7128 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7129 request.load_flags = 0;
7130
7131 SessionDependencies session_deps;
7132 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7133 true /* fail all reads */);
7134 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7135 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7136 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7137 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7138 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7139 session_deps.socket_factory.AddSSLSocketDataProvider(
7140 &ssl_socket_data_provider1);
7141 session_deps.socket_factory.AddSSLSocketDataProvider(
7142 &ssl_socket_data_provider2);
7143
7144 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7145 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7146 TestCompletionCallback callback;
7147
[email protected]5a1d7ca2010-04-28 20:12:277148 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217149 EXPECT_EQ(ERR_IO_PENDING, rv);
7150 EXPECT_EQ(OK, callback.WaitForResult());
7151
7152 const HttpResponseInfo* response = trans->GetResponseInfo();
7153 ASSERT_TRUE(response != NULL);
7154 ASSERT_TRUE(response->headers != NULL);
7155 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7156
7157 std::string response_data;
7158 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7159 EXPECT_EQ("ok.", response_data);
7160}
7161
[email protected]65041fa2010-05-21 06:56:537162// This tests the case that a request is issued via http instead of spdy after
7163// npn is negotiated.
7164TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387165 HttpStreamFactory::set_use_alternate_protocols(true);
7166 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537167 SessionDependencies session_deps;
7168 HttpRequestInfo request;
7169 request.method = "GET";
7170 request.url = GURL("https://www.google.com/");
7171 request.load_flags = 0;
7172
7173 MockWrite data_writes[] = {
7174 MockWrite("GET / HTTP/1.1\r\n"
7175 "Host: www.google.com\r\n"
7176 "Connection: keep-alive\r\n\r\n"),
7177 };
7178
7179 MockRead data_reads[] = {
7180 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357181 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537182 MockRead("hello world"),
7183 MockRead(false, OK),
7184 };
7185
7186 SSLSocketDataProvider ssl(true, OK);
7187 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7188 ssl.next_proto = "http/1.1";
7189
7190 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7191
7192 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7193 data_writes, arraysize(data_writes));
7194 session_deps.socket_factory.AddSocketDataProvider(&data);
7195
7196 TestCompletionCallback callback;
7197
7198 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7199 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7200
7201 int rv = trans->Start(&request, &callback, BoundNetLog());
7202
7203 EXPECT_EQ(ERR_IO_PENDING, rv);
7204 EXPECT_EQ(OK, callback.WaitForResult());
7205
7206 const HttpResponseInfo* response = trans->GetResponseInfo();
7207 ASSERT_TRUE(response != NULL);
7208 ASSERT_TRUE(response->headers != NULL);
7209 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7210
7211 std::string response_data;
7212 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7213 EXPECT_EQ("hello world", response_data);
7214
7215 EXPECT_FALSE(response->was_fetched_via_spdy);
7216 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:577217 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:537218
[email protected]8e6441ca2010-08-19 05:56:387219 HttpStreamFactory::set_next_protos("");
7220 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537221}
[email protected]26ef6582010-06-24 02:30:477222
7223TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7224 // Simulate the SSL handshake completing with an NPN negotiation
7225 // followed by an immediate server closing of the socket.
7226 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387227 HttpStreamFactory::set_use_alternate_protocols(true);
7228 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477229 SessionDependencies session_deps;
7230
7231 HttpRequestInfo request;
7232 request.method = "GET";
7233 request.url = GURL("https://www.google.com/");
7234 request.load_flags = 0;
7235
7236 SSLSocketDataProvider ssl(true, OK);
7237 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357238 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477239 ssl.was_npn_negotiated = true;
7240 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7241
[email protected]2bd93022010-07-17 00:58:447242 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137243 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477244
7245 MockRead spdy_reads[] = {
7246 MockRead(false, 0, 0) // Not async - return 0 immediately.
7247 };
7248
7249 scoped_refptr<DelayedSocketData> spdy_data(
7250 new DelayedSocketData(
7251 0, // don't wait in this case, immediate hangup.
7252 spdy_reads, arraysize(spdy_reads),
7253 spdy_writes, arraysize(spdy_writes)));
7254 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7255
7256 TestCompletionCallback callback;
7257
7258 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7259 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7260
7261 int rv = trans->Start(&request, &callback, BoundNetLog());
7262 EXPECT_EQ(ERR_IO_PENDING, rv);
7263 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7264
[email protected]8e6441ca2010-08-19 05:56:387265 HttpStreamFactory::set_next_protos("");
7266 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477267}
[email protected]65d34382010-07-01 18:12:267268
[email protected]f45c1ee2010-08-03 00:54:307269TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7270 // This test ensures that the URL passed into the proxy is upgraded
7271 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387272 HttpStreamFactory::set_use_alternate_protocols(true);
7273 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307274 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7275
[email protected]81cdfcd2010-10-16 00:49:007276 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307277 HttpAuthHandlerMock::Factory* auth_factory =
7278 new HttpAuthHandlerMock::Factory();
7279 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7280 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7281 auth_factory->set_do_init_from_challenge(true);
7282 session_deps.http_auth_handler_factory.reset(auth_factory);
7283
7284 HttpRequestInfo request;
7285 request.method = "GET";
7286 request.url = GURL("http://www.google.com");
7287 request.load_flags = 0;
7288
7289 // First round goes unauthenticated through the proxy.
7290 MockWrite data_writes_1[] = {
7291 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7292 "Host: www.google.com\r\n"
7293 "Proxy-Connection: keep-alive\r\n"
7294 "\r\n"),
7295 };
7296 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597297 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307298 MockRead("HTTP/1.1 200 OK\r\n"
7299 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7300 "Proxy-Connection: close\r\n"
7301 "\r\n"),
7302 };
7303 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7304 data_writes_1, arraysize(data_writes_1));
7305
7306 // Second round tries to tunnel to www.google.com due to the
7307 // Alternate-Protocol announcement in the first round. It fails due
7308 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597309 // After the failure, a tunnel is established to www.google.com using
7310 // Proxy-Authorization headers. There is then a SPDY request round.
7311 //
7312 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7313 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7314 // does a Disconnect and Connect on the same socket, rather than trying
7315 // to obtain a new one.
7316 //
7317 // NOTE: Originally, the proxy response to the second CONNECT request
7318 // simply returned another 407 so the unit test could skip the SSL connection
7319 // establishment and SPDY framing issues. Alas, the
7320 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307321 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597322
[email protected]f45c1ee2010-08-03 00:54:307323 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7324 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7325 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7326
[email protected]394816e92010-08-03 07:38:597327 MockWrite data_writes_2[] = {
7328 // First connection attempt without Proxy-Authorization.
7329 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7330 "Host: www.google.com\r\n"
7331 "Proxy-Connection: keep-alive\r\n"
7332 "\r\n"),
7333
7334 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307335 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7336 "Host: www.google.com\r\n"
7337 "Proxy-Connection: keep-alive\r\n"
7338 "Proxy-Authorization: auth_token\r\n"
7339 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307340
[email protected]394816e92010-08-03 07:38:597341 // SPDY request
7342 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307343 };
[email protected]394816e92010-08-03 07:38:597344 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7345 "Proxy-Authenticate: Mock\r\n"
7346 "Proxy-Connection: close\r\n"
7347 "\r\n");
7348 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7349 MockRead data_reads_2[] = {
7350 // First connection attempt fails
7351 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7352 MockRead(true, kRejectConnectResponse,
7353 arraysize(kRejectConnectResponse) - 1, 1),
7354
7355 // Second connection attempt passes
7356 MockRead(true, kAcceptConnectResponse,
7357 arraysize(kAcceptConnectResponse) -1, 4),
7358
7359 // SPDY response
7360 CreateMockRead(*resp.get(), 6),
7361 CreateMockRead(*data.get(), 6),
7362 MockRead(true, 0, 0, 6),
7363 };
7364 scoped_refptr<OrderedSocketData> data_2(
7365 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
7366 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:307367
7368 SSLSocketDataProvider ssl(true, OK);
7369 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7370 ssl.next_proto = "spdy/2";
7371 ssl.was_npn_negotiated = true;
7372
7373 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:597374 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:307375 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7376 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7377
7378 // First round should work and provide the Alternate-Protocol state.
7379 TestCompletionCallback callback_1;
7380 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
7381 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
7382 EXPECT_EQ(ERR_IO_PENDING, rv);
7383 EXPECT_EQ(OK, callback_1.WaitForResult());
7384
7385 // Second round should attempt a tunnel connect and get an auth challenge.
7386 TestCompletionCallback callback_2;
7387 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
7388 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
7389 EXPECT_EQ(ERR_IO_PENDING, rv);
7390 EXPECT_EQ(OK, callback_2.WaitForResult());
7391 const HttpResponseInfo* response = trans_2->GetResponseInfo();
7392 ASSERT_FALSE(response == NULL);
7393 ASSERT_FALSE(response->auth_challenge.get() == NULL);
7394
7395 // Restart with auth. Tunnel should work and response received.
7396 TestCompletionCallback callback_3;
7397 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
7398 EXPECT_EQ(ERR_IO_PENDING, rv);
7399 EXPECT_EQ(OK, callback_3.WaitForResult());
7400
7401 // After all that work, these two lines (or actually, just the scheme) are
7402 // what this test is all about. Make sure it happens correctly.
7403 const GURL& request_url = auth_handler->request_url();
7404 EXPECT_EQ("https", request_url.scheme());
7405 EXPECT_EQ("www.google.com", request_url.host());
7406
[email protected]8e6441ca2010-08-19 05:56:387407 HttpStreamFactory::set_next_protos("");
7408 HttpStreamFactory::set_use_alternate_protocols(false);
7409}
7410
7411// Test that if we cancel the transaction as the connection is completing, that
7412// everything tears down correctly.
7413TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
7414 // Setup everything about the connection to complete synchronously, so that
7415 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
7416 // for is the callback from the HttpStreamRequest.
7417 // Then cancel the transaction.
7418 // Verify that we don't crash.
7419 MockConnect mock_connect(false, OK);
7420 MockRead data_reads[] = {
7421 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
7422 MockRead(false, "hello world"),
7423 MockRead(false, OK),
7424 };
7425
7426 SessionDependencies session_deps;
7427 session_deps.host_resolver->set_synchronous_mode(true);
7428 scoped_ptr<HttpTransaction> trans(
7429 new HttpNetworkTransaction(CreateSession(&session_deps)));
7430
7431 HttpRequestInfo request;
7432 request.method = "GET";
7433 request.url = GURL("http://www.google.com/");
7434 request.load_flags = 0;
7435
7436 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7437 data.set_connect_data(mock_connect);
7438 session_deps.socket_factory.AddSocketDataProvider(&data);
7439
7440 TestCompletionCallback callback;
7441
7442 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7443 int rv = trans->Start(&request, &callback, log.bound());
7444 EXPECT_EQ(ERR_IO_PENDING, rv);
7445 trans.reset(); // Cancel the transaction here.
7446
7447 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:307448}
7449
[email protected]76a505b2010-08-25 06:23:007450// Test a basic GET request through a proxy.
7451TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:007452 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007453 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7454 session_deps.net_log = log.bound().net_log();
7455 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7456
[email protected]76a505b2010-08-25 06:23:007457 HttpRequestInfo request;
7458 request.method = "GET";
7459 request.url = GURL("http://www.google.com/");
7460
7461 MockWrite data_writes1[] = {
7462 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7463 "Host: www.google.com\r\n"
7464 "Proxy-Connection: keep-alive\r\n\r\n"),
7465 };
7466
7467 MockRead data_reads1[] = {
7468 MockRead("HTTP/1.1 200 OK\r\n"),
7469 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7470 MockRead("Content-Length: 100\r\n\r\n"),
7471 MockRead(false, OK),
7472 };
7473
7474 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7475 data_writes1, arraysize(data_writes1));
7476 session_deps.socket_factory.AddSocketDataProvider(&data1);
7477
7478 TestCompletionCallback callback1;
7479
[email protected]0b0bf032010-09-21 18:08:507480 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7481
[email protected]76a505b2010-08-25 06:23:007482 int rv = trans->Start(&request, &callback1, log.bound());
7483 EXPECT_EQ(ERR_IO_PENDING, rv);
7484
7485 rv = callback1.WaitForResult();
7486 EXPECT_EQ(OK, rv);
7487
7488 const HttpResponseInfo* response = trans->GetResponseInfo();
7489 ASSERT_FALSE(response == NULL);
7490
7491 EXPECT_TRUE(response->headers->IsKeepAlive());
7492 EXPECT_EQ(200, response->headers->response_code());
7493 EXPECT_EQ(100, response->headers->GetContentLength());
7494 EXPECT_TRUE(response->was_fetched_via_proxy);
7495 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7496}
7497
7498// Test a basic HTTPS GET request through a proxy.
7499TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:007500 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007501 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7502 session_deps.net_log = log.bound().net_log();
7503 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7504
[email protected]76a505b2010-08-25 06:23:007505 HttpRequestInfo request;
7506 request.method = "GET";
7507 request.url = GURL("https://www.google.com/");
7508
7509 // Since we have proxy, should try to establish tunnel.
7510 MockWrite data_writes1[] = {
7511 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7512 "Host: www.google.com\r\n"
7513 "Proxy-Connection: keep-alive\r\n\r\n"),
7514
7515 MockWrite("GET / HTTP/1.1\r\n"
7516 "Host: www.google.com\r\n"
7517 "Connection: keep-alive\r\n\r\n"),
7518 };
7519
7520 MockRead data_reads1[] = {
7521 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7522
7523 MockRead("HTTP/1.1 200 OK\r\n"),
7524 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7525 MockRead("Content-Length: 100\r\n\r\n"),
7526 MockRead(false, OK),
7527 };
7528
7529 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7530 data_writes1, arraysize(data_writes1));
7531 session_deps.socket_factory.AddSocketDataProvider(&data1);
7532 SSLSocketDataProvider ssl(true, OK);
7533 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7534
7535 TestCompletionCallback callback1;
7536
[email protected]0b0bf032010-09-21 18:08:507537 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7538
[email protected]76a505b2010-08-25 06:23:007539 int rv = trans->Start(&request, &callback1, log.bound());
7540 EXPECT_EQ(ERR_IO_PENDING, rv);
7541
7542 rv = callback1.WaitForResult();
7543 EXPECT_EQ(OK, rv);
7544 size_t pos = ExpectLogContainsSomewhere(
7545 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7546 NetLog::PHASE_NONE);
7547 ExpectLogContainsSomewhere(
7548 log.entries(), pos,
7549 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7550 NetLog::PHASE_NONE);
7551
7552 const HttpResponseInfo* response = trans->GetResponseInfo();
7553 ASSERT_FALSE(response == NULL);
7554
7555 EXPECT_TRUE(response->headers->IsKeepAlive());
7556 EXPECT_EQ(200, response->headers->response_code());
7557 EXPECT_EQ(100, response->headers->GetContentLength());
7558 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7559 EXPECT_TRUE(response->was_fetched_via_proxy);
7560}
7561
7562// Test a basic HTTPS GET request through a proxy, but the server hangs up
7563// while establishing the tunnel.
7564TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:007565 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007566 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7567 session_deps.net_log = log.bound().net_log();
7568 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7569
[email protected]76a505b2010-08-25 06:23:007570 HttpRequestInfo request;
7571 request.method = "GET";
7572 request.url = GURL("https://www.google.com/");
7573
7574 // Since we have proxy, should try to establish tunnel.
7575 MockWrite data_writes1[] = {
7576 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7577 "Host: www.google.com\r\n"
7578 "Proxy-Connection: keep-alive\r\n\r\n"),
7579
7580 MockWrite("GET / HTTP/1.1\r\n"
7581 "Host: www.google.com\r\n"
7582 "Connection: keep-alive\r\n\r\n"),
7583 };
7584
7585 MockRead data_reads1[] = {
7586 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
7587 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7588 MockRead(true, 0, 0), // EOF
7589 };
7590
7591 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7592 data_writes1, arraysize(data_writes1));
7593 session_deps.socket_factory.AddSocketDataProvider(&data1);
7594 SSLSocketDataProvider ssl(true, OK);
7595 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7596
7597 TestCompletionCallback callback1;
7598
[email protected]0b0bf032010-09-21 18:08:507599 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7600
[email protected]76a505b2010-08-25 06:23:007601 int rv = trans->Start(&request, &callback1, log.bound());
7602 EXPECT_EQ(ERR_IO_PENDING, rv);
7603
7604 rv = callback1.WaitForResult();
7605 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
7606 size_t pos = ExpectLogContainsSomewhere(
7607 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7608 NetLog::PHASE_NONE);
7609 ExpectLogContainsSomewhere(
7610 log.entries(), pos,
7611 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7612 NetLog::PHASE_NONE);
7613}
7614
[email protected]749eefa82010-09-13 22:14:037615// Test for crbug.com/55424.
7616TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
7617 SessionDependencies session_deps;
7618
7619 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
7620 "https://www.google.com", false, 1, LOWEST));
7621 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
7622
7623 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7624 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7625 MockRead spdy_reads[] = {
7626 CreateMockRead(*resp),
7627 CreateMockRead(*data),
7628 MockRead(true, 0, 0),
7629 };
7630
7631 scoped_refptr<DelayedSocketData> spdy_data(
7632 new DelayedSocketData(
7633 1, // wait for one write to finish before reading.
7634 spdy_reads, arraysize(spdy_reads),
7635 spdy_writes, arraysize(spdy_writes)));
7636 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7637
7638 SSLSocketDataProvider ssl(true, OK);
7639 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7640 ssl.next_proto = "spdy/2";
7641 ssl.was_npn_negotiated = true;
7642 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7643
7644 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7645
7646 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387647 HostPortPair host_port_pair("www.google.com", 443);
7648 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:037649 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:277650 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
7651 BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:277652 scoped_refptr<TCPSocketParams> tcp_params(
7653 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:387654 TestCompletionCallback callback;
7655
7656 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7657 EXPECT_EQ(ERR_IO_PENDING,
7658 connection->Init(host_port_pair.ToString(), tcp_params, LOWEST,
7659 &callback, session->tcp_socket_pool(),
7660 BoundNetLog()));
7661 EXPECT_EQ(OK, callback.WaitForResult());
7662 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:037663
7664 HttpRequestInfo request;
7665 request.method = "GET";
7666 request.url = GURL("https://www.google.com/");
7667 request.load_flags = 0;
7668
7669 // This is the important line that marks this as a preconnect.
7670 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
7671
7672 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7673
[email protected]749eefa82010-09-13 22:14:037674 int rv = trans->Start(&request, &callback, BoundNetLog());
7675 EXPECT_EQ(ERR_IO_PENDING, rv);
7676 EXPECT_EQ(OK, callback.WaitForResult());
7677}
7678
[email protected]89ceba9a2009-03-21 03:46:067679} // namespace net