blob: b25dcfbad82e0f679bad1d5952d738bb70a69705 [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]77848d12008-11-14 00:00:225#include <math.h> // ceil
[email protected]95d88ffe2010-02-04 21:25:336#include <vector>
[email protected]77848d12008-11-14 00:00:227
[email protected]68bf9152008-09-25 19:47:308#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:339#include "base/file_path.h"
10#include "base/file_util.h"
[email protected]bacff652009-03-31 17:50:3311#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3212#include "net/base/mock_host_resolver.h"
[email protected]ac790b42009-12-02 04:31:3113#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4214#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3315#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5216#include "net/base/test_completion_callback.h"
17#include "net/base/upload_data.h"
[email protected]dab9c7d2010-02-06 21:44:3218#include "net/spdy/spdy_session_pool.h"
[email protected]385a4672009-03-11 22:21:2919#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5720#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5221#include "net/http/http_network_session.h"
22#include "net/http/http_network_transaction.h"
[email protected]0877e3d2009-10-17 22:29:5723#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5224#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5325#include "net/proxy/proxy_config_service_fixed.h"
[email protected]f7984fc62009-06-22 23:26:4426#include "net/socket/client_socket_factory.h"
27#include "net/socket/socket_test_util.h"
28#include "net/socket/ssl_client_socket.h"
initial.commit586acc5fe2008-07-26 22:42:5229#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1530#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5231
32//-----------------------------------------------------------------------------
33
[email protected]89ceba9a2009-03-21 03:46:0634namespace net {
35
[email protected]e44de5d2009-06-05 20:12:4536// Helper to manage the lifetimes of the dependencies for a
37// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5938class SessionDependencies {
39 public:
40 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4241 SessionDependencies()
42 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:3743 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:1044 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]fa55e192010-02-15 14:25:5045 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]955fc2e72010-02-08 20:37:3046 spdy_session_pool(new SpdySessionPool) {}
[email protected]228ff742009-06-05 01:19:5947
48 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4549 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4250 : host_resolver(new MockHostResolver),
51 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1052 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]fa55e192010-02-15 14:25:5053 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]955fc2e72010-02-08 20:37:3054 spdy_session_pool(new SpdySessionPool) {}
[email protected]228ff742009-06-05 01:19:5955
[email protected]a2c2fb92009-07-18 07:31:0456 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0957 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4258 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5959 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:5060 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]955fc2e72010-02-08 20:37:3061 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]228ff742009-06-05 01:19:5962};
63
[email protected]1c773ea12009-04-28 19:58:4264ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5065 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:4866 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3967 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5368}
69
70
[email protected]228ff742009-06-05 01:19:5971HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]d13c3272010-02-04 00:24:5172 return new HttpNetworkSession(NULL,
73 session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:0974 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:4275 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:1076 session_deps->ssl_config_service,
[email protected]fa55e192010-02-15 14:25:5077 session_deps->spdy_session_pool,
78 session_deps->http_auth_handler_factory.get());
[email protected]e8d536192008-10-17 22:21:1479}
80
[email protected]89836e22008-09-25 20:33:4281class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:5282 public:
[email protected]0e75a732008-10-16 20:36:0983 virtual void TearDown() {
84 // Empty the current queue.
85 MessageLoop::current()->RunAllPending();
86 PlatformTest::TearDown();
87 }
88
[email protected]3d2a59b2008-09-26 19:44:2589 protected:
90 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:5291
[email protected]ff007e162009-05-23 09:13:1592 struct SimpleGetHelperResult {
93 int rv;
94 std::string status_line;
95 std::string response_data;
96 };
initial.commit586acc5fe2008-07-26 22:42:5297
[email protected]31a2bfe2010-02-09 08:03:3998 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
99 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15100 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52101
[email protected]228ff742009-06-05 01:19:59102 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40103 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43104 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52105
[email protected]ff007e162009-05-23 09:13:15106 HttpRequestInfo request;
107 request.method = "GET";
108 request.url = GURL("http://www.google.com/");
109 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52110
[email protected]31a2bfe2010-02-09 08:03:39111 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59112 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52113
[email protected]ff007e162009-05-23 09:13:15114 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52115
[email protected]684970b2009-08-14 04:54:46116 int rv = trans->Start(&request, &callback, NULL);
[email protected]ff007e162009-05-23 09:13:15117 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52118
[email protected]ff007e162009-05-23 09:13:15119 out.rv = callback.WaitForResult();
120 if (out.rv != OK)
121 return out;
122
123 const HttpResponseInfo* response = trans->GetResponseInfo();
124 EXPECT_TRUE(response != NULL);
125
126 EXPECT_TRUE(response->headers != NULL);
127 out.status_line = response->headers->GetStatusLine();
128
129 rv = ReadTransaction(trans.get(), &out.response_data);
130 EXPECT_EQ(OK, rv);
131
[email protected]aecfbf22008-10-16 02:02:47132 return out;
[email protected]ff007e162009-05-23 09:13:15133 }
initial.commit586acc5fe2008-07-26 22:42:52134
[email protected]ff007e162009-05-23 09:13:15135 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
136 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52137
[email protected]ff007e162009-05-23 09:13:15138 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15139};
[email protected]231d5a32008-09-13 00:45:27140
[email protected]15a5ccf82008-10-23 19:57:43141// Fill |str| with a long header list that consumes >= |size| bytes.
142void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19143 const char* row =
144 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
145 const int sizeof_row = strlen(row);
146 const int num_rows = static_cast<int>(
147 ceil(static_cast<float>(size) / sizeof_row));
148 const int sizeof_data = num_rows * sizeof_row;
149 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43150 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51151
[email protected]4ddaf2502008-10-23 18:26:19152 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43153 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19154}
155
[email protected]385a4672009-03-11 22:21:29156// Alternative functions that eliminate randomness and dependency on the local
157// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20158void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29159 static const uint8 bytes[] = {
160 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
161 };
162 static size_t current_byte = 0;
163 for (size_t i = 0; i < n; ++i) {
164 output[i] = bytes[current_byte++];
165 current_byte %= arraysize(bytes);
166 }
167}
168
[email protected]fe2bc6a2009-03-23 16:52:20169void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29170 static const uint8 bytes[] = {
171 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
172 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
173 };
174 static size_t current_byte = 0;
175 for (size_t i = 0; i < n; ++i) {
176 output[i] = bytes[current_byte++];
177 current_byte %= arraysize(bytes);
178 }
179}
180
[email protected]fe2bc6a2009-03-23 16:52:20181std::string MockGetHostName() {
182 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29183}
184
[email protected]a796bcec2010-03-22 17:17:26185template<typename EmulatedClientSocketPool, typename SocketSourceType>
186class CaptureGroupNameSocketPool : public EmulatedClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31187 public:
[email protected]a796bcec2010-03-22 17:17:26188 CaptureGroupNameSocketPool(HttpNetworkSession* session,
189 SocketSourceType* socket_source)
190 : EmulatedClientSocketPool(0, 0, "CaptureGroupNameTestPool",
191 session->host_resolver(), socket_source,
192 NULL) {}
[email protected]d80a4322009-08-14 07:07:49193 const std::string last_group_name_received() const {
194 return last_group_name_;
195 }
196
[email protected]684970b2009-08-14 04:54:46197 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49198 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31199 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31200 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46201 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53202 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31203 last_group_name_ = group_name;
204 return ERR_IO_PENDING;
205 }
[email protected]04e5be32009-06-26 20:00:31206 virtual void CancelRequest(const std::string& group_name,
207 const ClientSocketHandle* handle) { }
208 virtual void ReleaseSocket(const std::string& group_name,
209 ClientSocket* socket) {}
210 virtual void CloseIdleSockets() {}
211 virtual HostResolver* GetHostResolver() const {
212 return NULL;
213 }
214 virtual int IdleSocketCount() const {
215 return 0;
216 }
217 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
218 return 0;
219 }
220 virtual LoadState GetLoadState(const std::string& group_name,
221 const ClientSocketHandle* handle) const {
222 return LOAD_STATE_IDLE;
223 }
[email protected]a796bcec2010-03-22 17:17:26224 virtual base::TimeDelta ConnectionTimeout() const {
225 return base::TimeDelta();
226 }
[email protected]d80a4322009-08-14 07:07:49227
228 private:
[email protected]04e5be32009-06-26 20:00:31229 std::string last_group_name_;
230};
231
[email protected]a796bcec2010-03-22 17:17:26232typedef CaptureGroupNameSocketPool<TCPClientSocketPool, ClientSocketFactory>
233 CaptureGroupNameTCPSocketPool;
234typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool, TCPClientSocketPool>
235 CaptureGroupNameSOCKSSocketPool;
[email protected]231d5a32008-09-13 00:45:27236//-----------------------------------------------------------------------------
237
238TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59239 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40240 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43241 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27242}
243
244TEST_F(HttpNetworkTransactionTest, SimpleGET) {
245 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35246 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
247 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42248 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27249 };
[email protected]31a2bfe2010-02-09 08:03:39250 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
251 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42252 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27253 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
254 EXPECT_EQ("hello world", out.response_data);
255}
256
257// Response with no status line.
258TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
259 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35260 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42261 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27262 };
[email protected]31a2bfe2010-02-09 08:03:39263 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
264 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42265 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27266 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
267 EXPECT_EQ("hello world", out.response_data);
268}
269
270// Allow up to 4 bytes of junk to precede status line.
271TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
272 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35273 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42274 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27275 };
[email protected]31a2bfe2010-02-09 08:03:39276 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
277 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42278 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27279 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
280 EXPECT_EQ("DATA", out.response_data);
281}
282
283// Allow up to 4 bytes of junk to precede status line.
284TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
285 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35286 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42287 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27288 };
[email protected]31a2bfe2010-02-09 08:03:39289 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
290 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42291 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27292 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
293 EXPECT_EQ("DATA", out.response_data);
294}
295
296// Beyond 4 bytes of slop and it should fail to find a status line.
297TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
298 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35299 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42300 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27301 };
[email protected]31a2bfe2010-02-09 08:03:39302 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
303 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42304 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25305 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
306 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27307}
308
309// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
310TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
311 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35312 MockRead("\n"),
313 MockRead("\n"),
314 MockRead("Q"),
315 MockRead("J"),
316 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42317 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27318 };
[email protected]31a2bfe2010-02-09 08:03:39319 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
320 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42321 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27322 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
323 EXPECT_EQ("DATA", out.response_data);
324}
325
326// Close the connection before enough bytes to have a status line.
327TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
328 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35329 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42330 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27331 };
[email protected]31a2bfe2010-02-09 08:03:39332 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
333 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42334 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27335 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
336 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52337}
338
[email protected]f9d44aa2008-09-23 23:57:17339// Simulate a 204 response, lacking a Content-Length header, sent over a
340// persistent connection. The response should still terminate since a 204
341// cannot have a response body.
342TEST_F(HttpNetworkTransactionTest, StopsReading204) {
343 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35344 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
345 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42346 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17347 };
[email protected]31a2bfe2010-02-09 08:03:39348 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
349 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42350 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17351 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
352 EXPECT_EQ("", out.response_data);
353}
354
[email protected]0877e3d2009-10-17 22:29:57355// A simple request using chunked encoding with some extra data after.
356// (Like might be seen in a pipelined response.)
357TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
358 MockRead data_reads[] = {
359 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
360 MockRead("5\r\nHello\r\n"),
361 MockRead("1\r\n"),
362 MockRead(" \r\n"),
363 MockRead("5\r\nworld\r\n"),
364 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
365 MockRead(false, OK),
366 };
[email protected]31a2bfe2010-02-09 08:03:39367 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
368 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57369 EXPECT_EQ(OK, out.rv);
370 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
371 EXPECT_EQ("Hello world", out.response_data);
372}
373
[email protected]ef0faf2e72009-03-05 23:27:23374// Do a request using the HEAD method. Verify that we don't try to read the
375// message body (since HEAD has none).
376TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59377 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40378 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43379 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23380
[email protected]1c773ea12009-04-28 19:58:42381 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23382 request.method = "HEAD";
383 request.url = GURL("http://www.google.com/");
384 request.load_flags = 0;
385
386 MockWrite data_writes1[] = {
387 MockWrite("HEAD / HTTP/1.1\r\n"
388 "Host: www.google.com\r\n"
389 "Connection: keep-alive\r\n"
390 "Content-Length: 0\r\n\r\n"),
391 };
392 MockRead data_reads1[] = {
393 MockRead("HTTP/1.1 404 Not Found\r\n"),
394 MockRead("Server: Blah\r\n"),
395 MockRead("Content-Length: 1234\r\n\r\n"),
396
397 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42398 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23399 };
400
[email protected]31a2bfe2010-02-09 08:03:39401 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
402 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59403 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23404
405 TestCompletionCallback callback1;
406
[email protected]684970b2009-08-14 04:54:46407 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42408 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23409
410 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42411 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23412
[email protected]1c773ea12009-04-28 19:58:42413 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23414 EXPECT_FALSE(response == NULL);
415
416 // Check that the headers got parsed.
417 EXPECT_TRUE(response->headers != NULL);
418 EXPECT_EQ(1234, response->headers->GetContentLength());
419 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
420
421 std::string server_header;
422 void* iter = NULL;
423 bool has_server_header = response->headers->EnumerateHeader(
424 &iter, "Server", &server_header);
425 EXPECT_TRUE(has_server_header);
426 EXPECT_EQ("Blah", server_header);
427
428 // Reading should give EOF right away, since there is no message body
429 // (despite non-zero content-length).
430 std::string response_data;
431 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42432 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23433 EXPECT_EQ("", response_data);
434}
435
initial.commit586acc5fe2008-07-26 22:42:52436TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59437 SessionDependencies session_deps;
438 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52439
440 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35441 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
442 MockRead("hello"),
443 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
444 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42445 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52446 };
[email protected]31a2bfe2010-02-09 08:03:39447 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59448 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52449
450 const char* kExpectedResponseData[] = {
451 "hello", "world"
452 };
453
454 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43455 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52456
[email protected]1c773ea12009-04-28 19:58:42457 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52458 request.method = "GET";
459 request.url = GURL("http://www.google.com/");
460 request.load_flags = 0;
461
462 TestCompletionCallback callback;
463
[email protected]684970b2009-08-14 04:54:46464 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42465 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52466
467 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42468 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52469
[email protected]1c773ea12009-04-28 19:58:42470 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52471 EXPECT_TRUE(response != NULL);
472
473 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25474 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52475
476 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57477 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42478 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25479 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52480 }
481}
482
483TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59484 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40485 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43486 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52487
[email protected]1c773ea12009-04-28 19:58:42488 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52489 request.method = "POST";
490 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42491 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52492 request.upload_data->AppendBytes("foo", 3);
493 request.load_flags = 0;
494
495 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35496 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
497 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
498 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42499 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52500 };
[email protected]31a2bfe2010-02-09 08:03:39501 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59502 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52503
504 TestCompletionCallback callback;
505
[email protected]684970b2009-08-14 04:54:46506 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42507 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52508
509 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42510 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52511
[email protected]1c773ea12009-04-28 19:58:42512 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52513 EXPECT_TRUE(response != NULL);
514
515 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25516 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52517
518 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57519 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42520 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25521 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52522}
523
[email protected]3a2d3662009-03-27 03:49:14524// This test is almost the same as Ignores100 above, but the response contains
525// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57526// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14527TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59528 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40529 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43530 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14531
[email protected]1c773ea12009-04-28 19:58:42532 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14533 request.method = "GET";
534 request.url = GURL("http://www.foo.com/");
535 request.load_flags = 0;
536
537 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57538 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
539 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14540 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42541 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14542 };
[email protected]31a2bfe2010-02-09 08:03:39543 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59544 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14545
546 TestCompletionCallback callback;
547
[email protected]684970b2009-08-14 04:54:46548 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42549 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14550
551 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42552 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14553
[email protected]1c773ea12009-04-28 19:58:42554 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14555 EXPECT_TRUE(response != NULL);
556
557 EXPECT_TRUE(response->headers != NULL);
558 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
559
560 std::string response_data;
561 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42562 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14563 EXPECT_EQ("hello world", response_data);
564}
565
[email protected]ee9410e72010-01-07 01:42:38566TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
567 SessionDependencies session_deps;
568 scoped_ptr<HttpTransaction> trans(
569 new HttpNetworkTransaction(CreateSession(&session_deps)));
570
571 HttpRequestInfo request;
572 request.method = "POST";
573 request.url = GURL("http://www.foo.com/");
574 request.load_flags = 0;
575
576 MockRead data_reads[] = {
577 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
578 MockRead(true, 0),
579 };
[email protected]31a2bfe2010-02-09 08:03:39580 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38581 session_deps.socket_factory.AddSocketDataProvider(&data);
582
583 TestCompletionCallback callback;
584
585 int rv = trans->Start(&request, &callback, NULL);
586 EXPECT_EQ(ERR_IO_PENDING, rv);
587
588 rv = callback.WaitForResult();
589 EXPECT_EQ(OK, rv);
590
591 std::string response_data;
592 rv = ReadTransaction(trans.get(), &response_data);
593 EXPECT_EQ(OK, rv);
594 EXPECT_EQ("", response_data);
595}
596
597TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
598 SessionDependencies session_deps;
599 scoped_ptr<HttpTransaction> trans(
600 new HttpNetworkTransaction(CreateSession(&session_deps)));
601
602 HttpRequestInfo request;
603 request.method = "POST";
604 request.url = GURL("http://www.foo.com/");
605 request.load_flags = 0;
606
607 MockRead data_reads[] = {
608 MockRead(true, 0),
609 };
[email protected]31a2bfe2010-02-09 08:03:39610 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38611 session_deps.socket_factory.AddSocketDataProvider(&data);
612
613 TestCompletionCallback callback;
614
615 int rv = trans->Start(&request, &callback, NULL);
616 EXPECT_EQ(ERR_IO_PENDING, rv);
617
618 rv = callback.WaitForResult();
619 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
620}
621
[email protected]3d2a59b2008-09-26 19:44:25622// read_failure specifies a read failure that should cause the network
623// transaction to resend the request.
624void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
625 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59626 SessionDependencies session_deps;
627 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52628
[email protected]1c773ea12009-04-28 19:58:42629 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52630 request.method = "GET";
631 request.url = GURL("http://www.foo.com/");
632 request.load_flags = 0;
633
634 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35635 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
636 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25637 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52638 };
[email protected]31a2bfe2010-02-09 08:03:39639 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59640 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52641
642 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35643 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
644 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42645 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52646 };
[email protected]31a2bfe2010-02-09 08:03:39647 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59648 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52649
650 const char* kExpectedResponseData[] = {
651 "hello", "world"
652 };
653
654 for (int i = 0; i < 2; ++i) {
655 TestCompletionCallback callback;
656
[email protected]5695b8c2009-09-30 21:36:43657 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52658
[email protected]684970b2009-08-14 04:54:46659 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42660 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52661
662 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42663 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52664
[email protected]1c773ea12009-04-28 19:58:42665 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52666 EXPECT_TRUE(response != NULL);
667
668 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25669 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52670
671 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57672 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42673 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25674 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52675 }
676}
[email protected]3d2a59b2008-09-26 19:44:25677
678TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42679 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25680 KeepAliveConnectionResendRequestTest(read_failure);
681}
682
683TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42684 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25685 KeepAliveConnectionResendRequestTest(read_failure);
686}
687
688TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59689 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40690 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43691 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25692
[email protected]1c773ea12009-04-28 19:58:42693 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25694 request.method = "GET";
695 request.url = GURL("http://www.google.com/");
696 request.load_flags = 0;
697
698 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42699 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35700 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
701 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42702 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25703 };
[email protected]31a2bfe2010-02-09 08:03:39704 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59705 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25706
707 TestCompletionCallback callback;
708
[email protected]684970b2009-08-14 04:54:46709 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42710 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25711
712 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42713 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25714
[email protected]1c773ea12009-04-28 19:58:42715 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25716 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25717}
718
719// What do various browsers do when the server closes a non-keepalive
720// connection without sending any response header or body?
721//
722// IE7: error page
723// Safari 3.1.2 (Windows): error page
724// Firefox 3.0.1: blank page
725// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42726// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
727// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25728TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
729 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42730 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35731 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
732 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42733 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25734 };
[email protected]31a2bfe2010-02-09 08:03:39735 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
736 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42737 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25738}
[email protected]038e9a32008-10-08 22:40:16739
740// Test the request-challenge-retry sequence for basic auth.
741// (basic auth is the easiest to mock, because it has no randomness).
742TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59743 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40744 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43745 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16746
[email protected]1c773ea12009-04-28 19:58:42747 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16748 request.method = "GET";
749 request.url = GURL("http://www.google.com/");
750 request.load_flags = 0;
751
[email protected]f9ee6b52008-11-08 06:46:23752 MockWrite data_writes1[] = {
753 MockWrite("GET / HTTP/1.1\r\n"
754 "Host: www.google.com\r\n"
755 "Connection: keep-alive\r\n\r\n"),
756 };
757
[email protected]038e9a32008-10-08 22:40:16758 MockRead data_reads1[] = {
759 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
760 // Give a couple authenticate options (only the middle one is actually
761 // supported).
[email protected]22927ad2009-09-21 19:56:19762 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16763 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
764 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
765 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
766 // Large content-length -- won't matter, as connection will be reset.
767 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42768 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16769 };
770
771 // After calling trans->RestartWithAuth(), this is the request we should
772 // be issuing -- the final header line contains the credentials.
773 MockWrite data_writes2[] = {
774 MockWrite("GET / HTTP/1.1\r\n"
775 "Host: www.google.com\r\n"
776 "Connection: keep-alive\r\n"
777 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
778 };
779
780 // Lastly, the server responds with the actual content.
781 MockRead data_reads2[] = {
782 MockRead("HTTP/1.0 200 OK\r\n"),
783 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
784 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42785 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16786 };
787
[email protected]31a2bfe2010-02-09 08:03:39788 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
789 data_writes1, arraysize(data_writes1));
790 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
791 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59792 session_deps.socket_factory.AddSocketDataProvider(&data1);
793 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16794
795 TestCompletionCallback callback1;
796
[email protected]684970b2009-08-14 04:54:46797 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42798 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16799
800 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42801 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16802
[email protected]1c773ea12009-04-28 19:58:42803 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16804 EXPECT_FALSE(response == NULL);
805
806 // The password prompt info should have been set in response->auth_challenge.
807 EXPECT_FALSE(response->auth_challenge.get() == NULL);
808
[email protected]71e4573a2009-05-21 22:03:00809 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16810 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
811 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
812
813 TestCompletionCallback callback2;
814
815 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42816 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16817
818 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42819 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16820
821 response = trans->GetResponseInfo();
822 EXPECT_FALSE(response == NULL);
823 EXPECT_TRUE(response->auth_challenge.get() == NULL);
824 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16825}
826
[email protected]861fcd52009-08-26 02:33:46827TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
828 SessionDependencies session_deps;
829 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43830 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46831
832 HttpRequestInfo request;
833 request.method = "GET";
834 request.url = GURL("http://www.google.com/");
835 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
836
837 MockWrite data_writes[] = {
838 MockWrite("GET / HTTP/1.1\r\n"
839 "Host: www.google.com\r\n"
840 "Connection: keep-alive\r\n\r\n"),
841 };
842
843 MockRead data_reads[] = {
844 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
845 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
846 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
847 // Large content-length -- won't matter, as connection will be reset.
848 MockRead("Content-Length: 10000\r\n\r\n"),
849 MockRead(false, ERR_FAILED),
850 };
851
[email protected]31a2bfe2010-02-09 08:03:39852 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
853 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59854 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46855 TestCompletionCallback callback;
856
857 int rv = trans->Start(&request, &callback, NULL);
858 EXPECT_EQ(ERR_IO_PENDING, rv);
859
860 rv = callback.WaitForResult();
861 EXPECT_EQ(0, rv);
862
863 const HttpResponseInfo* response = trans->GetResponseInfo();
864 ASSERT_FALSE(response == NULL);
865 EXPECT_TRUE(response->auth_challenge.get() == NULL);
866}
867
[email protected]2d2697f92009-02-18 21:00:32868// Test the request-challenge-retry sequence for basic auth, over a keep-alive
869// connection.
870TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59871 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40872 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43873 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32874
[email protected]1c773ea12009-04-28 19:58:42875 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32876 request.method = "GET";
877 request.url = GURL("http://www.google.com/");
878 request.load_flags = 0;
879
880 MockWrite data_writes1[] = {
881 MockWrite("GET / HTTP/1.1\r\n"
882 "Host: www.google.com\r\n"
883 "Connection: keep-alive\r\n\r\n"),
884
885 // After calling trans->RestartWithAuth(), this is the request we should
886 // be issuing -- the final header line contains the credentials.
887 MockWrite("GET / HTTP/1.1\r\n"
888 "Host: www.google.com\r\n"
889 "Connection: keep-alive\r\n"
890 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
891 };
892
893 MockRead data_reads1[] = {
894 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
895 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
896 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
897 MockRead("Content-Length: 14\r\n\r\n"),
898 MockRead("Unauthorized\r\n"),
899
900 // Lastly, the server responds with the actual content.
901 MockRead("HTTP/1.1 200 OK\r\n"),
902 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
903 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42904 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32905 };
906
[email protected]31a2bfe2010-02-09 08:03:39907 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
908 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59909 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32910
911 TestCompletionCallback callback1;
912
[email protected]684970b2009-08-14 04:54:46913 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42914 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32915
916 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42917 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32918
[email protected]1c773ea12009-04-28 19:58:42919 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32920 EXPECT_FALSE(response == NULL);
921
922 // The password prompt info should have been set in response->auth_challenge.
923 EXPECT_FALSE(response->auth_challenge.get() == NULL);
924
[email protected]71e4573a2009-05-21 22:03:00925 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32926 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
927 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
928
929 TestCompletionCallback callback2;
930
931 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42932 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32933
934 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42935 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32936
937 response = trans->GetResponseInfo();
938 EXPECT_FALSE(response == NULL);
939 EXPECT_TRUE(response->auth_challenge.get() == NULL);
940 EXPECT_EQ(100, response->headers->GetContentLength());
941}
942
943// Test the request-challenge-retry sequence for basic auth, over a keep-alive
944// connection and with no response body to drain.
945TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59946 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40947 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43948 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32949
[email protected]1c773ea12009-04-28 19:58:42950 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32951 request.method = "GET";
952 request.url = GURL("http://www.google.com/");
953 request.load_flags = 0;
954
955 MockWrite data_writes1[] = {
956 MockWrite("GET / HTTP/1.1\r\n"
957 "Host: www.google.com\r\n"
958 "Connection: keep-alive\r\n\r\n"),
959
960 // After calling trans->RestartWithAuth(), this is the request we should
961 // be issuing -- the final header line contains the credentials.
962 MockWrite("GET / HTTP/1.1\r\n"
963 "Host: www.google.com\r\n"
964 "Connection: keep-alive\r\n"
965 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
966 };
967
[email protected]2d2697f92009-02-18 21:00:32968 MockRead data_reads1[] = {
969 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
970 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:31971 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:32972
973 // Lastly, the server responds with the actual content.
974 MockRead("HTTP/1.1 200 OK\r\n"),
975 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
976 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42977 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32978 };
979
[email protected]31a2bfe2010-02-09 08:03:39980 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
981 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59982 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32983
984 TestCompletionCallback callback1;
985
[email protected]684970b2009-08-14 04:54:46986 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42987 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32988
989 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42990 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32991
[email protected]1c773ea12009-04-28 19:58:42992 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32993 EXPECT_FALSE(response == NULL);
994
995 // The password prompt info should have been set in response->auth_challenge.
996 EXPECT_FALSE(response->auth_challenge.get() == NULL);
997
[email protected]71e4573a2009-05-21 22:03:00998 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32999 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1000 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1001
1002 TestCompletionCallback callback2;
1003
1004 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421005 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321006
1007 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421008 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321009
1010 response = trans->GetResponseInfo();
1011 EXPECT_FALSE(response == NULL);
1012 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1013 EXPECT_EQ(100, response->headers->GetContentLength());
1014}
1015
1016// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1017// connection and with a large response body to drain.
1018TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591019 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401020 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431021 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321022
[email protected]1c773ea12009-04-28 19:58:421023 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321024 request.method = "GET";
1025 request.url = GURL("http://www.google.com/");
1026 request.load_flags = 0;
1027
1028 MockWrite data_writes1[] = {
1029 MockWrite("GET / HTTP/1.1\r\n"
1030 "Host: www.google.com\r\n"
1031 "Connection: keep-alive\r\n\r\n"),
1032
1033 // After calling trans->RestartWithAuth(), this is the request we should
1034 // be issuing -- the final header line contains the credentials.
1035 MockWrite("GET / HTTP/1.1\r\n"
1036 "Host: www.google.com\r\n"
1037 "Connection: keep-alive\r\n"
1038 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1039 };
1040
1041 // Respond with 5 kb of response body.
1042 std::string large_body_string("Unauthorized");
1043 large_body_string.append(5 * 1024, ' ');
1044 large_body_string.append("\r\n");
1045
1046 MockRead data_reads1[] = {
1047 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1048 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1049 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1050 // 5134 = 12 + 5 * 1024 + 2
1051 MockRead("Content-Length: 5134\r\n\r\n"),
1052 MockRead(true, large_body_string.data(), large_body_string.size()),
1053
1054 // Lastly, the server responds with the actual content.
1055 MockRead("HTTP/1.1 200 OK\r\n"),
1056 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1057 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421058 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321059 };
1060
[email protected]31a2bfe2010-02-09 08:03:391061 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1062 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591063 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321064
1065 TestCompletionCallback callback1;
1066
[email protected]684970b2009-08-14 04:54:461067 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421068 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321069
1070 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421071 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321072
[email protected]1c773ea12009-04-28 19:58:421073 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321074 EXPECT_FALSE(response == NULL);
1075
1076 // The password prompt info should have been set in response->auth_challenge.
1077 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1078
[email protected]71e4573a2009-05-21 22:03:001079 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321080 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1081 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1082
1083 TestCompletionCallback callback2;
1084
1085 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421086 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321087
1088 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421089 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321090
1091 response = trans->GetResponseInfo();
1092 EXPECT_FALSE(response == NULL);
1093 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1094 EXPECT_EQ(100, response->headers->GetContentLength());
1095}
1096
1097// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311098// connection, but the server gets impatient and closes the connection.
1099TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1100 SessionDependencies session_deps;
1101 scoped_ptr<HttpTransaction> trans(
1102 new HttpNetworkTransaction(CreateSession(&session_deps)));
1103
1104 HttpRequestInfo request;
1105 request.method = "GET";
1106 request.url = GURL("http://www.google.com/");
1107 request.load_flags = 0;
1108
1109 MockWrite data_writes1[] = {
1110 MockWrite("GET / HTTP/1.1\r\n"
1111 "Host: www.google.com\r\n"
1112 "Connection: keep-alive\r\n\r\n"),
1113 // This simulates the seemingly successful write to a closed connection
1114 // if the bug is not fixed.
1115 MockWrite("GET / HTTP/1.1\r\n"
1116 "Host: www.google.com\r\n"
1117 "Connection: keep-alive\r\n"
1118 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1119 };
1120
1121 MockRead data_reads1[] = {
1122 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1123 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1124 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1125 MockRead("Content-Length: 14\r\n\r\n"),
1126 // Tell MockTCPClientSocket to simulate the server closing the connection.
1127 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1128 MockRead("Unauthorized\r\n"),
1129 MockRead(false, OK), // The server closes the connection.
1130 };
1131
1132 // After calling trans->RestartWithAuth(), this is the request we should
1133 // be issuing -- the final header line contains the credentials.
1134 MockWrite data_writes2[] = {
1135 MockWrite("GET / HTTP/1.1\r\n"
1136 "Host: www.google.com\r\n"
1137 "Connection: keep-alive\r\n"
1138 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1139 };
1140
1141 // Lastly, the server responds with the actual content.
1142 MockRead data_reads2[] = {
1143 MockRead("HTTP/1.1 200 OK\r\n"),
1144 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1145 MockRead("Content-Length: 100\r\n\r\n"),
1146 MockRead(false, OK),
1147 };
1148
[email protected]31a2bfe2010-02-09 08:03:391149 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1150 data_writes1, arraysize(data_writes1));
1151 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1152 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311153 session_deps.socket_factory.AddSocketDataProvider(&data1);
1154 session_deps.socket_factory.AddSocketDataProvider(&data2);
1155
1156 TestCompletionCallback callback1;
1157
1158 int rv = trans->Start(&request, &callback1, NULL);
1159 EXPECT_EQ(ERR_IO_PENDING, rv);
1160
1161 rv = callback1.WaitForResult();
1162 EXPECT_EQ(OK, rv);
1163
1164 const HttpResponseInfo* response = trans->GetResponseInfo();
1165 EXPECT_FALSE(response == NULL);
1166
1167 // The password prompt info should have been set in response->auth_challenge.
1168 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1169
1170 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1171 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1172 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1173
1174 TestCompletionCallback callback2;
1175
1176 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1177 EXPECT_EQ(ERR_IO_PENDING, rv);
1178
1179 rv = callback2.WaitForResult();
1180 EXPECT_EQ(OK, rv);
1181
1182 response = trans->GetResponseInfo();
1183 ASSERT_FALSE(response == NULL);
1184 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1185 EXPECT_EQ(100, response->headers->GetContentLength());
1186}
1187
1188// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321189// proxy connection, when setting up an SSL tunnel.
1190TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1191 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591192 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1193 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321194
[email protected]5695b8c2009-09-30 21:36:431195 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321196
[email protected]1c773ea12009-04-28 19:58:421197 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321198 request.method = "GET";
1199 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461200 // Ensure that proxy authentication is attempted even
1201 // when the no authentication data flag is set.
1202 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321203
1204 // Since we have proxy, should try to establish tunnel.
1205 MockWrite data_writes1[] = {
1206 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451207 "Host: www.google.com\r\n"
1208 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321209
1210 // After calling trans->RestartWithAuth(), this is the request we should
1211 // be issuing -- the final header line contains the credentials.
1212 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1213 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451214 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321215 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1216 };
1217
1218 // The proxy responds to the connect with a 407, using a persistent
1219 // connection.
1220 MockRead data_reads1[] = {
1221 // No credentials.
1222 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1223 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1224 MockRead("Content-Length: 10\r\n\r\n"),
1225 MockRead("0123456789"),
1226
1227 // Wrong credentials (wrong password).
1228 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1229 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1230 MockRead("Content-Length: 10\r\n\r\n"),
1231 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421232 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321233 };
1234
[email protected]31a2bfe2010-02-09 08:03:391235 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1236 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591237 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321238
1239 TestCompletionCallback callback1;
1240
[email protected]684970b2009-08-14 04:54:461241 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421242 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321243
1244 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421245 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321246
[email protected]1c773ea12009-04-28 19:58:421247 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321248 EXPECT_FALSE(response == NULL);
1249
1250 EXPECT_TRUE(response->headers->IsKeepAlive());
1251 EXPECT_EQ(407, response->headers->response_code());
1252 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421253 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321254
1255 // The password prompt info should have been set in response->auth_challenge.
1256 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1257
[email protected]71e4573a2009-05-21 22:03:001258 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321259 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1260 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1261
1262 TestCompletionCallback callback2;
1263
1264 // Wrong password (should be "bar").
1265 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421266 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321267
1268 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421269 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321270
1271 response = trans->GetResponseInfo();
1272 EXPECT_FALSE(response == NULL);
1273
1274 EXPECT_TRUE(response->headers->IsKeepAlive());
1275 EXPECT_EQ(407, response->headers->response_code());
1276 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421277 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321278
1279 // The password prompt info should have been set in response->auth_challenge.
1280 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1281
[email protected]71e4573a2009-05-21 22:03:001282 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321283 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1284 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1285}
1286
[email protected]a8e9b162009-03-12 00:06:441287// Test that we don't read the response body when we fail to establish a tunnel,
1288// even if the user cancels the proxy's auth attempt.
1289TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1290 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591291 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441292
[email protected]e44de5d2009-06-05 20:12:451293 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441294
[email protected]5695b8c2009-09-30 21:36:431295 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441296
[email protected]1c773ea12009-04-28 19:58:421297 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441298 request.method = "GET";
1299 request.url = GURL("https://www.google.com/");
1300 request.load_flags = 0;
1301
1302 // Since we have proxy, should try to establish tunnel.
1303 MockWrite data_writes[] = {
1304 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451305 "Host: www.google.com\r\n"
1306 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441307 };
1308
1309 // The proxy responds to the connect with a 407.
1310 MockRead data_reads[] = {
1311 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1312 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1313 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421314 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441315 };
1316
[email protected]31a2bfe2010-02-09 08:03:391317 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1318 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591319 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441320
1321 TestCompletionCallback callback;
1322
[email protected]684970b2009-08-14 04:54:461323 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421324 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441325
1326 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421327 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441328
[email protected]1c773ea12009-04-28 19:58:421329 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441330 EXPECT_FALSE(response == NULL);
1331
1332 EXPECT_TRUE(response->headers->IsKeepAlive());
1333 EXPECT_EQ(407, response->headers->response_code());
1334 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421335 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441336
1337 std::string response_data;
1338 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421339 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441340}
1341
[email protected]ff007e162009-05-23 09:13:151342void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081343 const MockRead& status, int expected_status) {
1344 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591345 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081346
[email protected]228ff742009-06-05 01:19:591347 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081348
[email protected]5695b8c2009-09-30 21:36:431349 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081350
[email protected]1c773ea12009-04-28 19:58:421351 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081352 request.method = "GET";
1353 request.url = GURL("https://www.google.com/");
1354 request.load_flags = 0;
1355
1356 // Since we have proxy, should try to establish tunnel.
1357 MockWrite data_writes[] = {
1358 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451359 "Host: www.google.com\r\n"
1360 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081361 };
1362
1363 MockRead data_reads[] = {
1364 status,
1365 MockRead("Content-Length: 10\r\n\r\n"),
1366 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421367 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081368 };
1369
[email protected]31a2bfe2010-02-09 08:03:391370 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1371 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591372 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081373
1374 TestCompletionCallback callback;
1375
[email protected]684970b2009-08-14 04:54:461376 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421377 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081378
1379 rv = callback.WaitForResult();
1380 EXPECT_EQ(expected_status, rv);
1381}
1382
[email protected]ff007e162009-05-23 09:13:151383void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081384 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421385 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081386}
1387
1388TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1389 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1390}
1391
1392TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1393 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1394}
1395
1396TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1397 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1398}
1399
1400TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1401 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1402}
1403
1404TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1405 ConnectStatusHelper(
1406 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1407}
1408
1409TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1410 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1411}
1412
1413TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1414 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1415}
1416
1417TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1418 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1419}
1420
1421TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1422 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1423}
1424
1425TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1426 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1427}
1428
1429TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1430 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1431}
1432
1433TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1434 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1435}
1436
1437TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1438 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1439}
1440
1441TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1442 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1443}
1444
1445TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1446 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1447}
1448
1449TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1450 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1451}
1452
1453TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1454 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1455}
1456
1457TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1458 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1459}
1460
1461TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1462 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1463}
1464
1465TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1466 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1467}
1468
1469TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1470 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1471}
1472
1473TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1474 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1475}
1476
1477TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1478 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1479}
1480
1481TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1482 ConnectStatusHelperWithExpectedStatus(
1483 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421484 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081485}
1486
1487TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1488 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1489}
1490
1491TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1492 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1493}
1494
1495TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1496 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1497}
1498
1499TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1500 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1501}
1502
1503TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1504 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1505}
1506
1507TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1508 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1509}
1510
1511TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1512 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1513}
1514
1515TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1516 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1517}
1518
1519TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1520 ConnectStatusHelper(
1521 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1522}
1523
1524TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1525 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1526}
1527
1528TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1529 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1530}
1531
1532TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1533 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1534}
1535
1536TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1537 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1538}
1539
1540TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1541 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1542}
1543
1544TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1545 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1546}
1547
1548TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1549 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1550}
1551
[email protected]038e9a32008-10-08 22:40:161552// Test the flow when both the proxy server AND origin server require
1553// authentication. Again, this uses basic auth for both since that is
1554// the simplest to mock.
1555TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591556 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011557
[email protected]038e9a32008-10-08 22:40:161558 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421559 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431560 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161561
[email protected]1c773ea12009-04-28 19:58:421562 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161563 request.method = "GET";
1564 request.url = GURL("http://www.google.com/");
1565 request.load_flags = 0;
1566
[email protected]f9ee6b52008-11-08 06:46:231567 MockWrite data_writes1[] = {
1568 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1569 "Host: www.google.com\r\n"
1570 "Proxy-Connection: keep-alive\r\n\r\n"),
1571 };
1572
[email protected]038e9a32008-10-08 22:40:161573 MockRead data_reads1[] = {
1574 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1575 // Give a couple authenticate options (only the middle one is actually
1576 // supported).
[email protected]22927ad2009-09-21 19:56:191577 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161578 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1579 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1580 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1581 // Large content-length -- won't matter, as connection will be reset.
1582 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421583 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161584 };
1585
1586 // After calling trans->RestartWithAuth() the first time, this is the
1587 // request we should be issuing -- the final header line contains the
1588 // proxy's credentials.
1589 MockWrite data_writes2[] = {
1590 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1591 "Host: www.google.com\r\n"
1592 "Proxy-Connection: keep-alive\r\n"
1593 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1594 };
1595
1596 // Now the proxy server lets the request pass through to origin server.
1597 // The origin server responds with a 401.
1598 MockRead data_reads2[] = {
1599 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1600 // Note: We are using the same realm-name as the proxy server. This is
1601 // completely valid, as realms are unique across hosts.
1602 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1603 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1604 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421605 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161606 };
1607
1608 // After calling trans->RestartWithAuth() the second time, we should send
1609 // the credentials for both the proxy and origin server.
1610 MockWrite data_writes3[] = {
1611 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1612 "Host: www.google.com\r\n"
1613 "Proxy-Connection: keep-alive\r\n"
1614 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1615 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1616 };
1617
1618 // Lastly we get the desired content.
1619 MockRead data_reads3[] = {
1620 MockRead("HTTP/1.0 200 OK\r\n"),
1621 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1622 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421623 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161624 };
1625
[email protected]31a2bfe2010-02-09 08:03:391626 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1627 data_writes1, arraysize(data_writes1));
1628 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1629 data_writes2, arraysize(data_writes2));
1630 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1631 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591632 session_deps.socket_factory.AddSocketDataProvider(&data1);
1633 session_deps.socket_factory.AddSocketDataProvider(&data2);
1634 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161635
1636 TestCompletionCallback callback1;
1637
[email protected]684970b2009-08-14 04:54:461638 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421639 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161640
1641 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421642 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161643
[email protected]1c773ea12009-04-28 19:58:421644 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161645 EXPECT_FALSE(response == NULL);
1646
1647 // The password prompt info should have been set in response->auth_challenge.
1648 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1649
[email protected]71e4573a2009-05-21 22:03:001650 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161651 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1652 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1653
1654 TestCompletionCallback callback2;
1655
1656 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421657 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161658
1659 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421660 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161661
1662 response = trans->GetResponseInfo();
1663 EXPECT_FALSE(response == NULL);
1664 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1665
[email protected]71e4573a2009-05-21 22:03:001666 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161667 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1668 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1669
1670 TestCompletionCallback callback3;
1671
1672 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421673 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161674
1675 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421676 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161677
1678 response = trans->GetResponseInfo();
1679 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1680 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161681}
[email protected]4ddaf2502008-10-23 18:26:191682
[email protected]ea9dc9a2009-09-05 00:43:321683// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1684// can't hook into its internals to cause it to generate predictable NTLM
1685// authorization headers.
1686#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291687// The NTLM authentication unit tests were generated by capturing the HTTP
1688// requests and responses using Fiddler 2 and inspecting the generated random
1689// bytes in the debugger.
1690
1691// Enter the correct password and authenticate successfully.
1692TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421693 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201694 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591695 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401696 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431697 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241698
[email protected]1c773ea12009-04-28 19:58:421699 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241700 request.method = "GET";
1701 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1702 request.load_flags = 0;
1703
1704 MockWrite data_writes1[] = {
1705 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1706 "Host: 172.22.68.17\r\n"
1707 "Connection: keep-alive\r\n\r\n"),
1708 };
1709
1710 MockRead data_reads1[] = {
1711 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1712 // Negotiate and NTLM are often requested together. We only support NTLM.
1713 MockRead("WWW-Authenticate: Negotiate\r\n"),
1714 MockRead("WWW-Authenticate: NTLM\r\n"),
1715 MockRead("Connection: close\r\n"),
1716 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361717 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241718 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421719 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241720 };
1721
1722 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221723 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241724 // request we should be issuing -- the final header line contains a Type
1725 // 1 message.
1726 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1727 "Host: 172.22.68.17\r\n"
1728 "Connection: keep-alive\r\n"
1729 "Authorization: NTLM "
1730 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1731
1732 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1733 // (the credentials for the origin server). The second request continues
1734 // on the same connection.
1735 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1736 "Host: 172.22.68.17\r\n"
1737 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291738 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1739 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1740 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1741 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1742 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241743 };
1744
1745 MockRead data_reads2[] = {
1746 // The origin server responds with a Type 2 message.
1747 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1748 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291749 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241750 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1751 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1752 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1753 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1754 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1755 "BtAAAAAAA=\r\n"),
1756 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361757 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241758 MockRead("You are not authorized to view this page\r\n"),
1759
1760 // Lastly we get the desired content.
1761 MockRead("HTTP/1.1 200 OK\r\n"),
1762 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1763 MockRead("Content-Length: 13\r\n\r\n"),
1764 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421765 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241766 };
1767
[email protected]31a2bfe2010-02-09 08:03:391768 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1769 data_writes1, arraysize(data_writes1));
1770 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1771 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591772 session_deps.socket_factory.AddSocketDataProvider(&data1);
1773 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241774
1775 TestCompletionCallback callback1;
1776
[email protected]684970b2009-08-14 04:54:461777 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421778 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241779
1780 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421781 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241782
[email protected]0757e7702009-03-27 04:00:221783 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1784 TestCompletionCallback callback2;
1785 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421786 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221787 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421788 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221789 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1790
[email protected]1c773ea12009-04-28 19:58:421791 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241792 EXPECT_FALSE(response == NULL);
1793
1794 // The password prompt info should have been set in response->auth_challenge.
1795 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1796
[email protected]71e4573a2009-05-21 22:03:001797 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241798 EXPECT_EQ(L"", response->auth_challenge->realm);
1799 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1800
[email protected]0757e7702009-03-27 04:00:221801 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241802
[email protected]0757e7702009-03-27 04:00:221803 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421804 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241805
[email protected]0757e7702009-03-27 04:00:221806 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421807 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241808
1809 response = trans->GetResponseInfo();
1810 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1811 EXPECT_EQ(13, response->headers->GetContentLength());
1812}
1813
[email protected]385a4672009-03-11 22:21:291814// Enter a wrong password, and then the correct one.
1815TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421816 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201817 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591818 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401819 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431820 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291821
[email protected]1c773ea12009-04-28 19:58:421822 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291823 request.method = "GET";
1824 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1825 request.load_flags = 0;
1826
1827 MockWrite data_writes1[] = {
1828 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1829 "Host: 172.22.68.17\r\n"
1830 "Connection: keep-alive\r\n\r\n"),
1831 };
1832
1833 MockRead data_reads1[] = {
1834 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1835 // Negotiate and NTLM are often requested together. We only support NTLM.
1836 MockRead("WWW-Authenticate: Negotiate\r\n"),
1837 MockRead("WWW-Authenticate: NTLM\r\n"),
1838 MockRead("Connection: close\r\n"),
1839 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361840 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291841 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421842 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291843 };
1844
1845 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221846 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291847 // request we should be issuing -- the final header line contains a Type
1848 // 1 message.
1849 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1850 "Host: 172.22.68.17\r\n"
1851 "Connection: keep-alive\r\n"
1852 "Authorization: NTLM "
1853 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1854
1855 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1856 // (the credentials for the origin server). The second request continues
1857 // on the same connection.
1858 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1859 "Host: 172.22.68.17\r\n"
1860 "Connection: keep-alive\r\n"
1861 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1862 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1863 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1864 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1865 "4Ww7b7E=\r\n\r\n"),
1866 };
1867
1868 MockRead data_reads2[] = {
1869 // The origin server responds with a Type 2 message.
1870 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1871 MockRead("WWW-Authenticate: NTLM "
1872 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1873 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1874 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1875 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1876 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1877 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1878 "BtAAAAAAA=\r\n"),
1879 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361880 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291881 MockRead("You are not authorized to view this page\r\n"),
1882
1883 // Wrong password.
1884 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1885 MockRead("WWW-Authenticate: Negotiate\r\n"),
1886 MockRead("WWW-Authenticate: NTLM\r\n"),
1887 MockRead("Connection: close\r\n"),
1888 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361889 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291890 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421891 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291892 };
1893
1894 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221895 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291896 // request we should be issuing -- the final header line contains a Type
1897 // 1 message.
1898 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1899 "Host: 172.22.68.17\r\n"
1900 "Connection: keep-alive\r\n"
1901 "Authorization: NTLM "
1902 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1903
1904 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1905 // (the credentials for the origin server). The second request continues
1906 // on the same connection.
1907 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1908 "Host: 172.22.68.17\r\n"
1909 "Connection: keep-alive\r\n"
1910 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1911 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1912 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1913 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1914 "+4MUm7c=\r\n\r\n"),
1915 };
1916
1917 MockRead data_reads3[] = {
1918 // The origin server responds with a Type 2 message.
1919 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1920 MockRead("WWW-Authenticate: NTLM "
1921 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1922 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1923 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1924 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1925 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1926 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1927 "BtAAAAAAA=\r\n"),
1928 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361929 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291930 MockRead("You are not authorized to view this page\r\n"),
1931
1932 // Lastly we get the desired content.
1933 MockRead("HTTP/1.1 200 OK\r\n"),
1934 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1935 MockRead("Content-Length: 13\r\n\r\n"),
1936 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421937 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291938 };
1939
[email protected]31a2bfe2010-02-09 08:03:391940 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1941 data_writes1, arraysize(data_writes1));
1942 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1943 data_writes2, arraysize(data_writes2));
1944 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1945 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591946 session_deps.socket_factory.AddSocketDataProvider(&data1);
1947 session_deps.socket_factory.AddSocketDataProvider(&data2);
1948 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:291949
1950 TestCompletionCallback callback1;
1951
[email protected]684970b2009-08-14 04:54:461952 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421953 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291954
1955 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421956 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291957
[email protected]0757e7702009-03-27 04:00:221958 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291959 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221960 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421961 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291962 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421963 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221964 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291965
[email protected]1c773ea12009-04-28 19:58:421966 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291967 EXPECT_FALSE(response == NULL);
1968
1969 // The password prompt info should have been set in response->auth_challenge.
1970 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1971
[email protected]71e4573a2009-05-21 22:03:001972 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291973 EXPECT_EQ(L"", response->auth_challenge->realm);
1974 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1975
1976 TestCompletionCallback callback3;
1977
[email protected]0757e7702009-03-27 04:00:221978 // Enter the wrong password.
1979 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421980 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291981
1982 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421983 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291984
[email protected]0757e7702009-03-27 04:00:221985 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1986 TestCompletionCallback callback4;
1987 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421988 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221989 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421990 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221991 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1992
1993 response = trans->GetResponseInfo();
1994 EXPECT_FALSE(response == NULL);
1995
1996 // The password prompt info should have been set in response->auth_challenge.
1997 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1998
[email protected]71e4573a2009-05-21 22:03:001999 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222000 EXPECT_EQ(L"", response->auth_challenge->realm);
2001 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2002
2003 TestCompletionCallback callback5;
2004
2005 // Now enter the right password.
2006 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422007 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222008
2009 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422010 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222011
[email protected]385a4672009-03-11 22:21:292012 response = trans->GetResponseInfo();
2013 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2014 EXPECT_EQ(13, response->headers->GetContentLength());
2015}
[email protected]ea9dc9a2009-09-05 00:43:322016#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292017
[email protected]4ddaf2502008-10-23 18:26:192018// Test reading a server response which has only headers, and no body.
2019// After some maximum number of bytes is consumed, the transaction should
2020// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2021TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592022 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402023 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432024 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192025
[email protected]1c773ea12009-04-28 19:58:422026 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192027 request.method = "GET";
2028 request.url = GURL("http://www.google.com/");
2029 request.load_flags = 0;
2030
[email protected]b75b7b2f2009-10-06 00:54:532031 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432032 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532033 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192034
2035 MockRead data_reads[] = {
2036 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432037 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192038 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422039 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192040 };
[email protected]31a2bfe2010-02-09 08:03:392041 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592042 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192043
2044 TestCompletionCallback callback;
2045
[email protected]684970b2009-08-14 04:54:462046 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422047 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192048
2049 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422050 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192051
[email protected]1c773ea12009-04-28 19:58:422052 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192053 EXPECT_TRUE(response == NULL);
2054}
[email protected]f4e426b2008-11-05 00:24:492055
2056// Make sure that we don't try to reuse a TCPClientSocket when failing to
2057// establish tunnel.
2058// http://code.google.com/p/chromium/issues/detail?id=3772
2059TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2060 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592061 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012062
[email protected]228ff742009-06-05 01:19:592063 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492064
[email protected]5695b8c2009-09-30 21:36:432065 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492066
[email protected]1c773ea12009-04-28 19:58:422067 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492068 request.method = "GET";
2069 request.url = GURL("https://www.google.com/");
2070 request.load_flags = 0;
2071
2072 // Since we have proxy, should try to establish tunnel.
2073 MockWrite data_writes1[] = {
2074 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452075 "Host: www.google.com\r\n"
2076 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492077 };
2078
[email protected]77848d12008-11-14 00:00:222079 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492080 // connection. Usually a proxy would return 501 (not implemented),
2081 // or 200 (tunnel established).
2082 MockRead data_reads1[] = {
2083 MockRead("HTTP/1.1 404 Not Found\r\n"),
2084 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422085 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492086 };
2087
[email protected]31a2bfe2010-02-09 08:03:392088 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2089 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592090 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492091
2092 TestCompletionCallback callback1;
2093
[email protected]684970b2009-08-14 04:54:462094 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422095 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492096
2097 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422098 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492099
[email protected]1c773ea12009-04-28 19:58:422100 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082101 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492102
[email protected]b4404c02009-04-10 16:38:522103 // Empty the current queue. This is necessary because idle sockets are
2104 // added to the connection pool asynchronously with a PostTask.
2105 MessageLoop::current()->RunAllPending();
2106
[email protected]f4e426b2008-11-05 00:24:492107 // We now check to make sure the TCPClientSocket was not added back to
2108 // the pool.
[email protected]a937a06d2009-08-19 21:19:242109 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492110 trans.reset();
[email protected]b4404c02009-04-10 16:38:522111 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492112 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242113 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492114}
[email protected]372d34a2008-11-05 21:30:512115
[email protected]1b157c02009-04-21 01:55:402116// Make sure that we recycle a socket after reading all of the response body.
2117TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592118 SessionDependencies session_deps;
2119 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402120
[email protected]5695b8c2009-09-30 21:36:432121 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402122
[email protected]1c773ea12009-04-28 19:58:422123 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402124 request.method = "GET";
2125 request.url = GURL("http://www.google.com/");
2126 request.load_flags = 0;
2127
2128 MockRead data_reads[] = {
2129 // A part of the response body is received with the response headers.
2130 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2131 // The rest of the response body is received in two parts.
2132 MockRead("lo"),
2133 MockRead(" world"),
2134 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422135 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402136 };
2137
[email protected]31a2bfe2010-02-09 08:03:392138 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592139 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402140
2141 TestCompletionCallback callback;
2142
[email protected]684970b2009-08-14 04:54:462143 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422144 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402145
2146 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422147 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402148
[email protected]1c773ea12009-04-28 19:58:422149 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402150 EXPECT_TRUE(response != NULL);
2151
2152 EXPECT_TRUE(response->headers != NULL);
2153 std::string status_line = response->headers->GetStatusLine();
2154 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2155
[email protected]a937a06d2009-08-19 21:19:242156 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402157
2158 std::string response_data;
2159 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422160 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402161 EXPECT_EQ("hello world", response_data);
2162
2163 // Empty the current queue. This is necessary because idle sockets are
2164 // added to the connection pool asynchronously with a PostTask.
2165 MessageLoop::current()->RunAllPending();
2166
2167 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242168 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402169}
2170
[email protected]b4404c02009-04-10 16:38:522171// Make sure that we recycle a socket after a zero-length response.
2172// http://crbug.com/9880
2173TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592174 SessionDependencies session_deps;
2175 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522176
[email protected]5695b8c2009-09-30 21:36:432177 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522178
[email protected]1c773ea12009-04-28 19:58:422179 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522180 request.method = "GET";
2181 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2182 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2183 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2184 "rt=prt.2642,ol.2649,xjs.2951");
2185 request.load_flags = 0;
2186
2187 MockRead data_reads[] = {
2188 MockRead("HTTP/1.1 204 No Content\r\n"
2189 "Content-Length: 0\r\n"
2190 "Content-Type: text/html\r\n\r\n"),
2191 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422192 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522193 };
2194
[email protected]31a2bfe2010-02-09 08:03:392195 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592196 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522197
2198 TestCompletionCallback callback;
2199
[email protected]684970b2009-08-14 04:54:462200 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422201 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522202
2203 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422204 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522205
[email protected]1c773ea12009-04-28 19:58:422206 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522207 EXPECT_TRUE(response != NULL);
2208
2209 EXPECT_TRUE(response->headers != NULL);
2210 std::string status_line = response->headers->GetStatusLine();
2211 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2212
[email protected]a937a06d2009-08-19 21:19:242213 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522214
2215 std::string response_data;
2216 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422217 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522218 EXPECT_EQ("", response_data);
2219
2220 // Empty the current queue. This is necessary because idle sockets are
2221 // added to the connection pool asynchronously with a PostTask.
2222 MessageLoop::current()->RunAllPending();
2223
2224 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242225 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522226}
2227
[email protected]372d34a2008-11-05 21:30:512228TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422229 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512230 // Transaction 1: a GET request that succeeds. The socket is recycled
2231 // after use.
2232 request[0].method = "GET";
2233 request[0].url = GURL("http://www.google.com/");
2234 request[0].load_flags = 0;
2235 // Transaction 2: a POST request. Reuses the socket kept alive from
2236 // transaction 1. The first attempts fails when writing the POST data.
2237 // This causes the transaction to retry with a new socket. The second
2238 // attempt succeeds.
2239 request[1].method = "POST";
2240 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422241 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512242 request[1].upload_data->AppendBytes("foo", 3);
2243 request[1].load_flags = 0;
2244
[email protected]228ff742009-06-05 01:19:592245 SessionDependencies session_deps;
2246 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512247
2248 // The first socket is used for transaction 1 and the first attempt of
2249 // transaction 2.
2250
2251 // The response of transaction 1.
2252 MockRead data_reads1[] = {
2253 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2254 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422255 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512256 };
2257 // The mock write results of transaction 1 and the first attempt of
2258 // transaction 2.
2259 MockWrite data_writes1[] = {
2260 MockWrite(false, 64), // GET
2261 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422262 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512263 };
[email protected]31a2bfe2010-02-09 08:03:392264 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2265 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512266
2267 // The second socket is used for the second attempt of transaction 2.
2268
2269 // The response of transaction 2.
2270 MockRead data_reads2[] = {
2271 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2272 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422273 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512274 };
2275 // The mock write results of the second attempt of transaction 2.
2276 MockWrite data_writes2[] = {
2277 MockWrite(false, 93), // POST
2278 MockWrite(false, 3), // POST data
2279 };
[email protected]31a2bfe2010-02-09 08:03:392280 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2281 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512282
[email protected]5ecc992a42009-11-11 01:41:592283 session_deps.socket_factory.AddSocketDataProvider(&data1);
2284 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512285
2286 const char* kExpectedResponseData[] = {
2287 "hello world", "welcome"
2288 };
2289
2290 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422291 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432292 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512293
2294 TestCompletionCallback callback;
2295
[email protected]684970b2009-08-14 04:54:462296 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422297 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512298
2299 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422300 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512301
[email protected]1c773ea12009-04-28 19:58:422302 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512303 EXPECT_TRUE(response != NULL);
2304
2305 EXPECT_TRUE(response->headers != NULL);
2306 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2307
2308 std::string response_data;
2309 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422310 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512311 EXPECT_EQ(kExpectedResponseData[i], response_data);
2312 }
2313}
[email protected]f9ee6b52008-11-08 06:46:232314
2315// Test the request-challenge-retry sequence for basic auth when there is
2316// an identity in the URL. The request should be sent as normal, but when
2317// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322318TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592319 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402320 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432321 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232322
[email protected]1c773ea12009-04-28 19:58:422323 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232324 request.method = "GET";
2325 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292326 request.url = GURL("http://foo:b@[email protected]/");
2327
2328 // The password contains an escaped character -- for this test to pass it
2329 // will need to be unescaped by HttpNetworkTransaction.
2330 EXPECT_EQ("b%40r", request.url.password());
2331
[email protected]ea9dc9a2009-09-05 00:43:322332 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232333
2334 MockWrite data_writes1[] = {
2335 MockWrite("GET / HTTP/1.1\r\n"
2336 "Host: www.google.com\r\n"
2337 "Connection: keep-alive\r\n\r\n"),
2338 };
2339
2340 MockRead data_reads1[] = {
2341 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2342 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2343 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422344 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232345 };
2346
2347 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322348 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232349 MockWrite data_writes2[] = {
2350 MockWrite("GET / HTTP/1.1\r\n"
2351 "Host: www.google.com\r\n"
2352 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292353 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232354 };
2355
2356 MockRead data_reads2[] = {
2357 MockRead("HTTP/1.0 200 OK\r\n"),
2358 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422359 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232360 };
2361
[email protected]31a2bfe2010-02-09 08:03:392362 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2363 data_writes1, arraysize(data_writes1));
2364 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2365 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592366 session_deps.socket_factory.AddSocketDataProvider(&data1);
2367 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232368
2369 TestCompletionCallback callback1;
2370
[email protected]684970b2009-08-14 04:54:462371 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422372 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232373
2374 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422375 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232376
[email protected]0757e7702009-03-27 04:00:222377 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2378 TestCompletionCallback callback2;
2379 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422380 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222381 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422382 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222383 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2384
[email protected]1c773ea12009-04-28 19:58:422385 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232386 EXPECT_FALSE(response == NULL);
2387
2388 // There is no challenge info, since the identity in URL worked.
2389 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2390
2391 EXPECT_EQ(100, response->headers->GetContentLength());
2392
2393 // Empty the current queue.
2394 MessageLoop::current()->RunAllPending();
2395}
2396
[email protected]ea9dc9a2009-09-05 00:43:322397// Test the request-challenge-retry sequence for basic auth when there is
2398// an incorrect identity in the URL. The identity from the URL should be used
2399// only once.
2400TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2401 SessionDependencies session_deps;
2402 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432403 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322404
2405 HttpRequestInfo request;
2406 request.method = "GET";
2407 // Note: the URL has a username:password in it. The password "baz" is
2408 // wrong (should be "bar").
2409 request.url = GURL("http://foo:[email protected]/");
2410
2411 request.load_flags = LOAD_NORMAL;
2412
2413 MockWrite data_writes1[] = {
2414 MockWrite("GET / HTTP/1.1\r\n"
2415 "Host: www.google.com\r\n"
2416 "Connection: keep-alive\r\n\r\n"),
2417 };
2418
2419 MockRead data_reads1[] = {
2420 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2421 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2422 MockRead("Content-Length: 10\r\n\r\n"),
2423 MockRead(false, ERR_FAILED),
2424 };
2425
2426 // After the challenge above, the transaction will be restarted using the
2427 // identity from the url (foo, baz) to answer the challenge.
2428 MockWrite data_writes2[] = {
2429 MockWrite("GET / HTTP/1.1\r\n"
2430 "Host: www.google.com\r\n"
2431 "Connection: keep-alive\r\n"
2432 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2433 };
2434
2435 MockRead data_reads2[] = {
2436 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2437 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2438 MockRead("Content-Length: 10\r\n\r\n"),
2439 MockRead(false, ERR_FAILED),
2440 };
2441
2442 // After the challenge above, the transaction will be restarted using the
2443 // identity supplied by the user (foo, bar) to answer the challenge.
2444 MockWrite data_writes3[] = {
2445 MockWrite("GET / HTTP/1.1\r\n"
2446 "Host: www.google.com\r\n"
2447 "Connection: keep-alive\r\n"
2448 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2449 };
2450
2451 MockRead data_reads3[] = {
2452 MockRead("HTTP/1.0 200 OK\r\n"),
2453 MockRead("Content-Length: 100\r\n\r\n"),
2454 MockRead(false, OK),
2455 };
2456
[email protected]31a2bfe2010-02-09 08:03:392457 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2458 data_writes1, arraysize(data_writes1));
2459 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2460 data_writes2, arraysize(data_writes2));
2461 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2462 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592463 session_deps.socket_factory.AddSocketDataProvider(&data1);
2464 session_deps.socket_factory.AddSocketDataProvider(&data2);
2465 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322466
2467 TestCompletionCallback callback1;
2468
2469 int rv = trans->Start(&request, &callback1, NULL);
2470 EXPECT_EQ(ERR_IO_PENDING, rv);
2471
2472 rv = callback1.WaitForResult();
2473 EXPECT_EQ(OK, rv);
2474
2475 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2476 TestCompletionCallback callback2;
2477 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2478 EXPECT_EQ(ERR_IO_PENDING, rv);
2479 rv = callback2.WaitForResult();
2480 EXPECT_EQ(OK, rv);
2481 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2482
2483 const HttpResponseInfo* response = trans->GetResponseInfo();
2484 EXPECT_FALSE(response == NULL);
2485 // The password prompt info should have been set in response->auth_challenge.
2486 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2487
2488 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2489 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2490 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2491
2492 TestCompletionCallback callback3;
2493 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2494 EXPECT_EQ(ERR_IO_PENDING, rv);
2495 rv = callback3.WaitForResult();
2496 EXPECT_EQ(OK, rv);
2497 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2498
2499 response = trans->GetResponseInfo();
2500 EXPECT_FALSE(response == NULL);
2501
2502 // There is no challenge info, since the identity worked.
2503 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2504
2505 EXPECT_EQ(100, response->headers->GetContentLength());
2506
2507 // Empty the current queue.
2508 MessageLoop::current()->RunAllPending();
2509}
2510
[email protected]f9ee6b52008-11-08 06:46:232511// Test that previously tried username/passwords for a realm get re-used.
2512TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592513 SessionDependencies session_deps;
2514 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232515
2516 // Transaction 1: authenticate (foo, bar) on MyRealm1
2517 {
[email protected]5695b8c2009-09-30 21:36:432518 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232519
[email protected]1c773ea12009-04-28 19:58:422520 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232521 request.method = "GET";
2522 request.url = GURL("http://www.google.com/x/y/z");
2523 request.load_flags = 0;
2524
2525 MockWrite data_writes1[] = {
2526 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2527 "Host: www.google.com\r\n"
2528 "Connection: keep-alive\r\n\r\n"),
2529 };
2530
2531 MockRead data_reads1[] = {
2532 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2533 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2534 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422535 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232536 };
2537
2538 // Resend with authorization (username=foo, password=bar)
2539 MockWrite data_writes2[] = {
2540 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2541 "Host: www.google.com\r\n"
2542 "Connection: keep-alive\r\n"
2543 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2544 };
2545
2546 // Sever accepts the authorization.
2547 MockRead data_reads2[] = {
2548 MockRead("HTTP/1.0 200 OK\r\n"),
2549 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422550 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232551 };
2552
[email protected]31a2bfe2010-02-09 08:03:392553 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2554 data_writes1, arraysize(data_writes1));
2555 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2556 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592557 session_deps.socket_factory.AddSocketDataProvider(&data1);
2558 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232559
2560 TestCompletionCallback callback1;
2561
[email protected]684970b2009-08-14 04:54:462562 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422563 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232564
2565 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422566 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232567
[email protected]1c773ea12009-04-28 19:58:422568 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232569 EXPECT_FALSE(response == NULL);
2570
2571 // The password prompt info should have been set in
2572 // response->auth_challenge.
2573 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2574
[email protected]71e4573a2009-05-21 22:03:002575 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232576 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2577 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2578
2579 TestCompletionCallback callback2;
2580
2581 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422582 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232583
2584 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422585 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232586
2587 response = trans->GetResponseInfo();
2588 EXPECT_FALSE(response == NULL);
2589 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2590 EXPECT_EQ(100, response->headers->GetContentLength());
2591 }
2592
2593 // ------------------------------------------------------------------------
2594
2595 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2596 {
[email protected]5695b8c2009-09-30 21:36:432597 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232598
[email protected]1c773ea12009-04-28 19:58:422599 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232600 request.method = "GET";
2601 // Note that Transaction 1 was at /x/y/z, so this is in the same
2602 // protection space as MyRealm1.
2603 request.url = GURL("http://www.google.com/x/y/a/b");
2604 request.load_flags = 0;
2605
2606 MockWrite data_writes1[] = {
2607 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2608 "Host: www.google.com\r\n"
2609 "Connection: keep-alive\r\n"
2610 // Send preemptive authorization for MyRealm1
2611 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2612 };
2613
2614 // The server didn't like the preemptive authorization, and
2615 // challenges us for a different realm (MyRealm2).
2616 MockRead data_reads1[] = {
2617 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2618 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2619 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422620 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232621 };
2622
2623 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2624 MockWrite data_writes2[] = {
2625 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2626 "Host: www.google.com\r\n"
2627 "Connection: keep-alive\r\n"
2628 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2629 };
2630
2631 // Sever accepts the authorization.
2632 MockRead data_reads2[] = {
2633 MockRead("HTTP/1.0 200 OK\r\n"),
2634 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422635 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232636 };
2637
[email protected]31a2bfe2010-02-09 08:03:392638 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2639 data_writes1, arraysize(data_writes1));
2640 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2641 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592642 session_deps.socket_factory.AddSocketDataProvider(&data1);
2643 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232644
2645 TestCompletionCallback callback1;
2646
[email protected]684970b2009-08-14 04:54:462647 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422648 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232649
2650 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422651 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232652
[email protected]1c773ea12009-04-28 19:58:422653 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232654 EXPECT_FALSE(response == NULL);
2655
2656 // The password prompt info should have been set in
2657 // response->auth_challenge.
2658 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2659
[email protected]71e4573a2009-05-21 22:03:002660 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232661 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2662 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2663
2664 TestCompletionCallback callback2;
2665
2666 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422667 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232668
2669 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422670 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232671
2672 response = trans->GetResponseInfo();
2673 EXPECT_FALSE(response == NULL);
2674 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2675 EXPECT_EQ(100, response->headers->GetContentLength());
2676 }
2677
2678 // ------------------------------------------------------------------------
2679
2680 // Transaction 3: Resend a request in MyRealm's protection space --
2681 // succeed with preemptive authorization.
2682 {
[email protected]5695b8c2009-09-30 21:36:432683 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232684
[email protected]1c773ea12009-04-28 19:58:422685 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232686 request.method = "GET";
2687 request.url = GURL("http://www.google.com/x/y/z2");
2688 request.load_flags = 0;
2689
2690 MockWrite data_writes1[] = {
2691 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2692 "Host: www.google.com\r\n"
2693 "Connection: keep-alive\r\n"
2694 // The authorization for MyRealm1 gets sent preemptively
2695 // (since the url is in the same protection space)
2696 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2697 };
2698
2699 // Sever accepts the preemptive authorization
2700 MockRead data_reads1[] = {
2701 MockRead("HTTP/1.0 200 OK\r\n"),
2702 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422703 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232704 };
2705
[email protected]31a2bfe2010-02-09 08:03:392706 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2707 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592708 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232709
2710 TestCompletionCallback callback1;
2711
[email protected]684970b2009-08-14 04:54:462712 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422713 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232714
2715 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422716 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232717
[email protected]1c773ea12009-04-28 19:58:422718 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232719 EXPECT_FALSE(response == NULL);
2720
2721 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2722 EXPECT_EQ(100, response->headers->GetContentLength());
2723 }
2724
2725 // ------------------------------------------------------------------------
2726
2727 // Transaction 4: request another URL in MyRealm (however the
2728 // url is not known to belong to the protection space, so no pre-auth).
2729 {
[email protected]5695b8c2009-09-30 21:36:432730 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232731
[email protected]1c773ea12009-04-28 19:58:422732 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232733 request.method = "GET";
2734 request.url = GURL("http://www.google.com/x/1");
2735 request.load_flags = 0;
2736
2737 MockWrite data_writes1[] = {
2738 MockWrite("GET /x/1 HTTP/1.1\r\n"
2739 "Host: www.google.com\r\n"
2740 "Connection: keep-alive\r\n\r\n"),
2741 };
2742
2743 MockRead data_reads1[] = {
2744 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2745 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2746 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422747 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232748 };
2749
2750 // Resend with authorization from MyRealm's cache.
2751 MockWrite data_writes2[] = {
2752 MockWrite("GET /x/1 HTTP/1.1\r\n"
2753 "Host: www.google.com\r\n"
2754 "Connection: keep-alive\r\n"
2755 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2756 };
2757
2758 // Sever accepts the authorization.
2759 MockRead data_reads2[] = {
2760 MockRead("HTTP/1.0 200 OK\r\n"),
2761 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422762 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232763 };
2764
[email protected]31a2bfe2010-02-09 08:03:392765 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2766 data_writes1, arraysize(data_writes1));
2767 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2768 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592769 session_deps.socket_factory.AddSocketDataProvider(&data1);
2770 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232771
2772 TestCompletionCallback callback1;
2773
[email protected]684970b2009-08-14 04:54:462774 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422775 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232776
2777 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422778 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232779
[email protected]0757e7702009-03-27 04:00:222780 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2781 TestCompletionCallback callback2;
2782 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422783 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222784 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422785 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222786 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2787
[email protected]1c773ea12009-04-28 19:58:422788 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232789 EXPECT_FALSE(response == NULL);
2790 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2791 EXPECT_EQ(100, response->headers->GetContentLength());
2792 }
2793
2794 // ------------------------------------------------------------------------
2795
2796 // Transaction 5: request a URL in MyRealm, but the server rejects the
2797 // cached identity. Should invalidate and re-prompt.
2798 {
[email protected]5695b8c2009-09-30 21:36:432799 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232800
[email protected]1c773ea12009-04-28 19:58:422801 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232802 request.method = "GET";
2803 request.url = GURL("http://www.google.com/p/q/t");
2804 request.load_flags = 0;
2805
2806 MockWrite data_writes1[] = {
2807 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2808 "Host: www.google.com\r\n"
2809 "Connection: keep-alive\r\n\r\n"),
2810 };
2811
2812 MockRead data_reads1[] = {
2813 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2814 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2815 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422816 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232817 };
2818
2819 // Resend with authorization from cache for MyRealm.
2820 MockWrite data_writes2[] = {
2821 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2822 "Host: www.google.com\r\n"
2823 "Connection: keep-alive\r\n"
2824 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2825 };
2826
2827 // Sever rejects the authorization.
2828 MockRead data_reads2[] = {
2829 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2830 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2831 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422832 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232833 };
2834
2835 // At this point we should prompt for new credentials for MyRealm.
2836 // Restart with username=foo3, password=foo4.
2837 MockWrite data_writes3[] = {
2838 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2839 "Host: www.google.com\r\n"
2840 "Connection: keep-alive\r\n"
2841 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2842 };
2843
2844 // Sever accepts the authorization.
2845 MockRead data_reads3[] = {
2846 MockRead("HTTP/1.0 200 OK\r\n"),
2847 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422848 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232849 };
2850
[email protected]31a2bfe2010-02-09 08:03:392851 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2852 data_writes1, arraysize(data_writes1));
2853 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2854 data_writes2, arraysize(data_writes2));
2855 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2856 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592857 session_deps.socket_factory.AddSocketDataProvider(&data1);
2858 session_deps.socket_factory.AddSocketDataProvider(&data2);
2859 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232860
2861 TestCompletionCallback callback1;
2862
[email protected]684970b2009-08-14 04:54:462863 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422864 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232865
2866 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422867 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232868
[email protected]0757e7702009-03-27 04:00:222869 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2870 TestCompletionCallback callback2;
2871 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422872 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222873 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422874 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222875 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2876
[email protected]1c773ea12009-04-28 19:58:422877 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232878 EXPECT_FALSE(response == NULL);
2879
2880 // The password prompt info should have been set in
2881 // response->auth_challenge.
2882 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2883
[email protected]71e4573a2009-05-21 22:03:002884 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232885 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2886 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2887
[email protected]0757e7702009-03-27 04:00:222888 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232889
[email protected]0757e7702009-03-27 04:00:222890 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422891 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232892
[email protected]0757e7702009-03-27 04:00:222893 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422894 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232895
2896 response = trans->GetResponseInfo();
2897 EXPECT_FALSE(response == NULL);
2898 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2899 EXPECT_EQ(100, response->headers->GetContentLength());
2900 }
2901}
[email protected]89ceba9a2009-03-21 03:46:062902
2903// Test the ResetStateForRestart() private method.
2904TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2905 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592906 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402907 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432908 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062909
2910 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062911 trans->read_buf_ = new IOBuffer(15);
2912 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572913 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062914
2915 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:142916 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:572917 response->auth_challenge = new AuthChallengeInfo();
2918 response->ssl_info.cert_status = -15;
2919 response->response_time = base::Time::Now();
2920 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062921
2922 { // Setup state for response_.vary_data
2923 HttpRequestInfo request;
2924 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2925 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:572926 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]89ceba9a2009-03-21 03:46:062927 request.extra_headers = "Foo: 1\nbar: 23";
[email protected]0877e3d2009-10-17 22:29:572928 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:062929 }
2930
2931 // Cause the above state to be reset.
2932 trans->ResetStateForRestart();
2933
2934 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:072935 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:062936 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:572937 EXPECT_EQ(0U, trans->request_headers_.size());
2938 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2939 EXPECT_TRUE(response->headers.get() == NULL);
2940 EXPECT_EQ(false, response->was_cached);
2941 EXPECT_EQ(0, response->ssl_info.cert_status);
2942 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:062943}
2944
[email protected]bacff652009-03-31 17:50:332945// Test HTTPS connections to a site with a bad certificate
2946TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592947 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402948 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432949 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332950
2951 HttpRequestInfo request;
2952 request.method = "GET";
2953 request.url = GURL("https://www.google.com/");
2954 request.load_flags = 0;
2955
2956 MockWrite data_writes[] = {
2957 MockWrite("GET / HTTP/1.1\r\n"
2958 "Host: www.google.com\r\n"
2959 "Connection: keep-alive\r\n\r\n"),
2960 };
2961
2962 MockRead data_reads[] = {
2963 MockRead("HTTP/1.0 200 OK\r\n"),
2964 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2965 MockRead("Content-Length: 100\r\n\r\n"),
2966 MockRead(false, OK),
2967 };
2968
[email protected]5ecc992a42009-11-11 01:41:592969 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:392970 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2971 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592972 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2973 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:332974
[email protected]5ecc992a42009-11-11 01:41:592975 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2976 session_deps.socket_factory.AddSocketDataProvider(&data);
2977 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2978 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:332979
2980 TestCompletionCallback callback;
2981
[email protected]684970b2009-08-14 04:54:462982 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332983 EXPECT_EQ(ERR_IO_PENDING, rv);
2984
2985 rv = callback.WaitForResult();
2986 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2987
2988 rv = trans->RestartIgnoringLastError(&callback);
2989 EXPECT_EQ(ERR_IO_PENDING, rv);
2990
2991 rv = callback.WaitForResult();
2992 EXPECT_EQ(OK, rv);
2993
2994 const HttpResponseInfo* response = trans->GetResponseInfo();
2995
2996 EXPECT_FALSE(response == NULL);
2997 EXPECT_EQ(100, response->headers->GetContentLength());
2998}
2999
3000// Test HTTPS connections to a site with a bad certificate, going through a
3001// proxy
3002TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593003 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333004
3005 HttpRequestInfo request;
3006 request.method = "GET";
3007 request.url = GURL("https://www.google.com/");
3008 request.load_flags = 0;
3009
3010 MockWrite proxy_writes[] = {
3011 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453012 "Host: www.google.com\r\n"
3013 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333014 };
3015
3016 MockRead proxy_reads[] = {
3017 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423018 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333019 };
3020
3021 MockWrite data_writes[] = {
3022 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453023 "Host: www.google.com\r\n"
3024 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333025 MockWrite("GET / HTTP/1.1\r\n"
3026 "Host: www.google.com\r\n"
3027 "Connection: keep-alive\r\n\r\n"),
3028 };
3029
3030 MockRead data_reads[] = {
3031 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3032 MockRead("HTTP/1.0 200 OK\r\n"),
3033 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3034 MockRead("Content-Length: 100\r\n\r\n"),
3035 MockRead(false, OK),
3036 };
3037
[email protected]31a2bfe2010-02-09 08:03:393038 StaticSocketDataProvider ssl_bad_certificate(
3039 proxy_reads, arraysize(proxy_reads),
3040 proxy_writes, arraysize(proxy_writes));
3041 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3042 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593043 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3044 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333045
[email protected]5ecc992a42009-11-11 01:41:593046 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3047 session_deps.socket_factory.AddSocketDataProvider(&data);
3048 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3049 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333050
3051 TestCompletionCallback callback;
3052
3053 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593054 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333055
[email protected]d207a5f2009-06-04 05:28:403056 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433057 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333058
[email protected]684970b2009-08-14 04:54:463059 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:333060 EXPECT_EQ(ERR_IO_PENDING, rv);
3061
3062 rv = callback.WaitForResult();
3063 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3064
3065 rv = trans->RestartIgnoringLastError(&callback);
3066 EXPECT_EQ(ERR_IO_PENDING, rv);
3067
3068 rv = callback.WaitForResult();
3069 EXPECT_EQ(OK, rv);
3070
3071 const HttpResponseInfo* response = trans->GetResponseInfo();
3072
3073 EXPECT_FALSE(response == NULL);
3074 EXPECT_EQ(100, response->headers->GetContentLength());
3075 }
3076}
3077
[email protected]1c773ea12009-04-28 19:58:423078TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593079 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403080 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433081 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423082
3083 HttpRequestInfo request;
3084 request.method = "GET";
3085 request.url = GURL("http://www.google.com/");
3086 request.user_agent = "Chromium Ultra Awesome X Edition";
3087
3088 MockWrite data_writes[] = {
3089 MockWrite("GET / HTTP/1.1\r\n"
3090 "Host: www.google.com\r\n"
3091 "Connection: keep-alive\r\n"
3092 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3093 };
3094
3095 // Lastly, the server responds with the actual content.
3096 MockRead data_reads[] = {
3097 MockRead("HTTP/1.0 200 OK\r\n"),
3098 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3099 MockRead("Content-Length: 100\r\n\r\n"),
3100 MockRead(false, OK),
3101 };
3102
[email protected]31a2bfe2010-02-09 08:03:393103 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3104 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593105 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423106
3107 TestCompletionCallback callback;
3108
[email protected]684970b2009-08-14 04:54:463109 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423110 EXPECT_EQ(ERR_IO_PENDING, rv);
3111
3112 rv = callback.WaitForResult();
3113 EXPECT_EQ(OK, rv);
3114}
3115
3116TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593117 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403118 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433119 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423120
3121 HttpRequestInfo request;
3122 request.method = "GET";
3123 request.url = GURL("http://www.google.com/");
3124 request.load_flags = 0;
3125 request.referrer = GURL("http://the.previous.site.com/");
3126
3127 MockWrite data_writes[] = {
3128 MockWrite("GET / HTTP/1.1\r\n"
3129 "Host: www.google.com\r\n"
3130 "Connection: keep-alive\r\n"
3131 "Referer: http://the.previous.site.com/\r\n\r\n"),
3132 };
3133
3134 // Lastly, the server responds with the actual content.
3135 MockRead data_reads[] = {
3136 MockRead("HTTP/1.0 200 OK\r\n"),
3137 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3138 MockRead("Content-Length: 100\r\n\r\n"),
3139 MockRead(false, OK),
3140 };
3141
[email protected]31a2bfe2010-02-09 08:03:393142 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3143 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593144 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423145
3146 TestCompletionCallback callback;
3147
[email protected]684970b2009-08-14 04:54:463148 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423149 EXPECT_EQ(ERR_IO_PENDING, rv);
3150
3151 rv = callback.WaitForResult();
3152 EXPECT_EQ(OK, rv);
3153}
3154
3155TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593156 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403157 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433158 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423159
3160 HttpRequestInfo request;
3161 request.method = "POST";
3162 request.url = GURL("http://www.google.com/");
3163
3164 MockWrite data_writes[] = {
3165 MockWrite("POST / HTTP/1.1\r\n"
3166 "Host: www.google.com\r\n"
3167 "Connection: keep-alive\r\n"
3168 "Content-Length: 0\r\n\r\n"),
3169 };
3170
3171 // Lastly, the server responds with the actual content.
3172 MockRead data_reads[] = {
3173 MockRead("HTTP/1.0 200 OK\r\n"),
3174 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3175 MockRead("Content-Length: 100\r\n\r\n"),
3176 MockRead(false, OK),
3177 };
3178
[email protected]31a2bfe2010-02-09 08:03:393179 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3180 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593181 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423182
3183 TestCompletionCallback callback;
3184
[email protected]684970b2009-08-14 04:54:463185 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423186 EXPECT_EQ(ERR_IO_PENDING, rv);
3187
3188 rv = callback.WaitForResult();
3189 EXPECT_EQ(OK, rv);
3190}
3191
3192TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593193 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403194 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433195 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423196
3197 HttpRequestInfo request;
3198 request.method = "PUT";
3199 request.url = GURL("http://www.google.com/");
3200
3201 MockWrite data_writes[] = {
3202 MockWrite("PUT / HTTP/1.1\r\n"
3203 "Host: www.google.com\r\n"
3204 "Connection: keep-alive\r\n"
3205 "Content-Length: 0\r\n\r\n"),
3206 };
3207
3208 // Lastly, the server responds with the actual content.
3209 MockRead data_reads[] = {
3210 MockRead("HTTP/1.0 200 OK\r\n"),
3211 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3212 MockRead("Content-Length: 100\r\n\r\n"),
3213 MockRead(false, OK),
3214 };
3215
[email protected]31a2bfe2010-02-09 08:03:393216 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3217 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593218 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423219
3220 TestCompletionCallback callback;
3221
[email protected]684970b2009-08-14 04:54:463222 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423223 EXPECT_EQ(ERR_IO_PENDING, rv);
3224
3225 rv = callback.WaitForResult();
3226 EXPECT_EQ(OK, rv);
3227}
3228
3229TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593230 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403231 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433232 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423233
3234 HttpRequestInfo request;
3235 request.method = "HEAD";
3236 request.url = GURL("http://www.google.com/");
3237
3238 MockWrite data_writes[] = {
3239 MockWrite("HEAD / HTTP/1.1\r\n"
3240 "Host: www.google.com\r\n"
3241 "Connection: keep-alive\r\n"
3242 "Content-Length: 0\r\n\r\n"),
3243 };
3244
3245 // Lastly, the server responds with the actual content.
3246 MockRead data_reads[] = {
3247 MockRead("HTTP/1.0 200 OK\r\n"),
3248 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3249 MockRead("Content-Length: 100\r\n\r\n"),
3250 MockRead(false, OK),
3251 };
3252
[email protected]31a2bfe2010-02-09 08:03:393253 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3254 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593255 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423256
3257 TestCompletionCallback callback;
3258
[email protected]684970b2009-08-14 04:54:463259 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423260 EXPECT_EQ(ERR_IO_PENDING, rv);
3261
3262 rv = callback.WaitForResult();
3263 EXPECT_EQ(OK, rv);
3264}
3265
3266TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593267 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403268 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433269 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423270
3271 HttpRequestInfo request;
3272 request.method = "GET";
3273 request.url = GURL("http://www.google.com/");
3274 request.load_flags = LOAD_BYPASS_CACHE;
3275
3276 MockWrite data_writes[] = {
3277 MockWrite("GET / HTTP/1.1\r\n"
3278 "Host: www.google.com\r\n"
3279 "Connection: keep-alive\r\n"
3280 "Pragma: no-cache\r\n"
3281 "Cache-Control: no-cache\r\n\r\n"),
3282 };
3283
3284 // Lastly, the server responds with the actual content.
3285 MockRead data_reads[] = {
3286 MockRead("HTTP/1.0 200 OK\r\n"),
3287 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3288 MockRead("Content-Length: 100\r\n\r\n"),
3289 MockRead(false, OK),
3290 };
3291
[email protected]31a2bfe2010-02-09 08:03:393292 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3293 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593294 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423295
3296 TestCompletionCallback callback;
3297
[email protected]684970b2009-08-14 04:54:463298 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423299 EXPECT_EQ(ERR_IO_PENDING, rv);
3300
3301 rv = callback.WaitForResult();
3302 EXPECT_EQ(OK, rv);
3303}
3304
3305TEST_F(HttpNetworkTransactionTest,
3306 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593307 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403308 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433309 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423310
3311 HttpRequestInfo request;
3312 request.method = "GET";
3313 request.url = GURL("http://www.google.com/");
3314 request.load_flags = LOAD_VALIDATE_CACHE;
3315
3316 MockWrite data_writes[] = {
3317 MockWrite("GET / HTTP/1.1\r\n"
3318 "Host: www.google.com\r\n"
3319 "Connection: keep-alive\r\n"
3320 "Cache-Control: max-age=0\r\n\r\n"),
3321 };
3322
3323 // Lastly, the server responds with the actual content.
3324 MockRead data_reads[] = {
3325 MockRead("HTTP/1.0 200 OK\r\n"),
3326 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3327 MockRead("Content-Length: 100\r\n\r\n"),
3328 MockRead(false, OK),
3329 };
3330
[email protected]31a2bfe2010-02-09 08:03:393331 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3332 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593333 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423334
3335 TestCompletionCallback callback;
3336
[email protected]684970b2009-08-14 04:54:463337 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423338 EXPECT_EQ(ERR_IO_PENDING, rv);
3339
3340 rv = callback.WaitForResult();
3341 EXPECT_EQ(OK, rv);
3342}
3343
3344TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593345 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403346 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433347 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423348
3349 HttpRequestInfo request;
3350 request.method = "GET";
3351 request.url = GURL("http://www.google.com/");
3352 request.extra_headers = "FooHeader: Bar\r\n";
3353
3354 MockWrite data_writes[] = {
3355 MockWrite("GET / HTTP/1.1\r\n"
3356 "Host: www.google.com\r\n"
3357 "Connection: keep-alive\r\n"
3358 "FooHeader: Bar\r\n\r\n"),
3359 };
3360
3361 // Lastly, the server responds with the actual content.
3362 MockRead data_reads[] = {
3363 MockRead("HTTP/1.0 200 OK\r\n"),
3364 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3365 MockRead("Content-Length: 100\r\n\r\n"),
3366 MockRead(false, OK),
3367 };
3368
[email protected]31a2bfe2010-02-09 08:03:393369 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3370 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593371 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423372
3373 TestCompletionCallback callback;
3374
[email protected]684970b2009-08-14 04:54:463375 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423376 EXPECT_EQ(ERR_IO_PENDING, rv);
3377
3378 rv = callback.WaitForResult();
3379 EXPECT_EQ(OK, rv);
3380}
3381
[email protected]3cd17242009-06-23 02:59:023382TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093383 SessionDependencies session_deps(
3384 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023385
3386 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433387 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023388
3389 HttpRequestInfo request;
3390 request.method = "GET";
3391 request.url = GURL("http://www.google.com/");
3392 request.load_flags = 0;
3393
3394 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3395 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3396
3397 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353398 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023399 MockWrite("GET / HTTP/1.1\r\n"
3400 "Host: www.google.com\r\n"
3401 "Connection: keep-alive\r\n\r\n")
3402 };
3403
3404 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593405 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023406 MockRead("HTTP/1.0 200 OK\r\n"),
3407 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3408 MockRead("Payload"),
3409 MockRead(false, OK)
3410 };
3411
[email protected]31a2bfe2010-02-09 08:03:393412 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3413 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593414 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023415
3416 TestCompletionCallback callback;
3417
[email protected]684970b2009-08-14 04:54:463418 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023419 EXPECT_EQ(ERR_IO_PENDING, rv);
3420
3421 rv = callback.WaitForResult();
3422 EXPECT_EQ(OK, rv);
3423
3424 const HttpResponseInfo* response = trans->GetResponseInfo();
3425 EXPECT_FALSE(response == NULL);
3426
3427 std::string response_text;
3428 rv = ReadTransaction(trans.get(), &response_text);
3429 EXPECT_EQ(OK, rv);
3430 EXPECT_EQ("Payload", response_text);
3431}
3432
3433TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093434 SessionDependencies session_deps(
3435 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023436
3437 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433438 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023439
3440 HttpRequestInfo request;
3441 request.method = "GET";
3442 request.url = GURL("https://www.google.com/");
3443 request.load_flags = 0;
3444
3445 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3446 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3447
3448 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353449 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3450 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023451 MockWrite("GET / HTTP/1.1\r\n"
3452 "Host: www.google.com\r\n"
3453 "Connection: keep-alive\r\n\r\n")
3454 };
3455
3456 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353457 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3458 arraysize(read_buffer)),
3459 MockRead("HTTP/1.0 200 OK\r\n"),
3460 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3461 MockRead("Payload"),
3462 MockRead(false, OK)
3463 };
3464
[email protected]31a2bfe2010-02-09 08:03:393465 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3466 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593467 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353468
[email protected]5ecc992a42009-11-11 01:41:593469 SSLSocketDataProvider ssl(true, OK);
3470 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353471
3472 TestCompletionCallback callback;
3473
[email protected]684970b2009-08-14 04:54:463474 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353475 EXPECT_EQ(ERR_IO_PENDING, rv);
3476
3477 rv = callback.WaitForResult();
3478 EXPECT_EQ(OK, rv);
3479
3480 const HttpResponseInfo* response = trans->GetResponseInfo();
3481 EXPECT_FALSE(response == NULL);
3482
3483 std::string response_text;
3484 rv = ReadTransaction(trans.get(), &response_text);
3485 EXPECT_EQ(OK, rv);
3486 EXPECT_EQ("Payload", response_text);
3487}
3488
3489TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093490 SessionDependencies session_deps(
3491 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353492
3493 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433494 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353495
3496 HttpRequestInfo request;
3497 request.method = "GET";
3498 request.url = GURL("http://www.google.com/");
3499 request.load_flags = 0;
3500
3501 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3502 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373503 const char kSOCKS5OkRequest[] = {
3504 0x05, // Version
3505 0x01, // Command (CONNECT)
3506 0x00, // Reserved.
3507 0x03, // Address type (DOMAINNAME).
3508 0x0E, // Length of domain (14)
3509 // Domain string:
3510 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3511 0x00, 0x50, // 16-bit port (80)
3512 };
[email protected]e0c27be2009-07-15 13:09:353513 const char kSOCKS5OkResponse[] =
3514 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3515
3516 MockWrite data_writes[] = {
3517 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3518 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3519 MockWrite("GET / HTTP/1.1\r\n"
3520 "Host: www.google.com\r\n"
3521 "Connection: keep-alive\r\n\r\n")
3522 };
3523
3524 MockRead data_reads[] = {
3525 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3526 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3527 MockRead("HTTP/1.0 200 OK\r\n"),
3528 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3529 MockRead("Payload"),
3530 MockRead(false, OK)
3531 };
3532
[email protected]31a2bfe2010-02-09 08:03:393533 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3534 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593535 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353536
3537 TestCompletionCallback callback;
3538
[email protected]684970b2009-08-14 04:54:463539 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353540 EXPECT_EQ(ERR_IO_PENDING, rv);
3541
3542 rv = callback.WaitForResult();
3543 EXPECT_EQ(OK, rv);
3544
3545 const HttpResponseInfo* response = trans->GetResponseInfo();
3546 EXPECT_FALSE(response == NULL);
3547
3548 std::string response_text;
3549 rv = ReadTransaction(trans.get(), &response_text);
3550 EXPECT_EQ(OK, rv);
3551 EXPECT_EQ("Payload", response_text);
3552}
3553
3554TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093555 SessionDependencies session_deps(
3556 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353557
3558 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433559 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353560
3561 HttpRequestInfo request;
3562 request.method = "GET";
3563 request.url = GURL("https://www.google.com/");
3564 request.load_flags = 0;
3565
3566 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3567 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373568 const unsigned char kSOCKS5OkRequest[] = {
3569 0x05, // Version
3570 0x01, // Command (CONNECT)
3571 0x00, // Reserved.
3572 0x03, // Address type (DOMAINNAME).
3573 0x0E, // Length of domain (14)
3574 // Domain string:
3575 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3576 0x01, 0xBB, // 16-bit port (443)
3577 };
3578
[email protected]e0c27be2009-07-15 13:09:353579 const char kSOCKS5OkResponse[] =
3580 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3581
3582 MockWrite data_writes[] = {
3583 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3584 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3585 arraysize(kSOCKS5OkRequest)),
3586 MockWrite("GET / HTTP/1.1\r\n"
3587 "Host: www.google.com\r\n"
3588 "Connection: keep-alive\r\n\r\n")
3589 };
3590
3591 MockRead data_reads[] = {
3592 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3593 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023594 MockRead("HTTP/1.0 200 OK\r\n"),
3595 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3596 MockRead("Payload"),
3597 MockRead(false, OK)
3598 };
3599
[email protected]31a2bfe2010-02-09 08:03:393600 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3601 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593602 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023603
[email protected]5ecc992a42009-11-11 01:41:593604 SSLSocketDataProvider ssl(true, OK);
3605 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023606
3607 TestCompletionCallback callback;
3608
[email protected]684970b2009-08-14 04:54:463609 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023610 EXPECT_EQ(ERR_IO_PENDING, rv);
3611
3612 rv = callback.WaitForResult();
3613 EXPECT_EQ(OK, rv);
3614
3615 const HttpResponseInfo* response = trans->GetResponseInfo();
3616 EXPECT_FALSE(response == NULL);
3617
3618 std::string response_text;
3619 rv = ReadTransaction(trans.get(), &response_text);
3620 EXPECT_EQ(OK, rv);
3621 EXPECT_EQ("Payload", response_text);
3622}
3623
[email protected]04e5be32009-06-26 20:00:313624// Tests that for connection endpoints the group names are correctly set.
3625TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3626 const struct {
3627 const std::string proxy_server;
3628 const std::string url;
3629 const std::string expected_group_name;
3630 } tests[] = {
3631 {
3632 "", // no proxy (direct)
3633 "http://www.google.com/direct",
3634 "http://www.google.com/",
3635 },
3636 {
3637 "http_proxy",
3638 "http://www.google.com/http_proxy_normal",
3639 "proxy/http_proxy:80/",
3640 },
3641 {
3642 "socks4://socks_proxy:1080",
3643 "http://www.google.com/socks4_direct",
3644 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3645 },
3646
3647 // SSL Tests
3648 {
3649 "",
3650 "https://www.google.com/direct_ssl",
3651 "https://www.google.com/",
3652 },
3653 {
3654 "http_proxy",
3655 "https://www.google.com/http_connect_ssl",
3656 "proxy/http_proxy:80/https://www.google.com/",
3657 },
3658 {
3659 "socks4://socks_proxy:1080",
3660 "https://www.google.com/socks4_ssl",
3661 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3662 },
3663 };
3664
3665 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093666 SessionDependencies session_deps(
3667 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313668
[email protected]04e5be32009-06-26 20:00:313669 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a796bcec2010-03-22 17:17:263670
3671 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
3672 new CaptureGroupNameTCPSocketPool(session.get(),
3673 session->socket_factory()));
3674 session->tcp_socket_pool_ = tcp_conn_pool.get();
3675 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
3676 new CaptureGroupNameSOCKSSocketPool(session.get(),
3677 tcp_conn_pool.get()));
3678 session->socks_socket_pool_ = socks_conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313679
[email protected]5695b8c2009-09-30 21:36:433680 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313681
3682 HttpRequestInfo request;
3683 request.method = "GET";
3684 request.url = GURL(tests[i].url);
3685 request.load_flags = 0;
3686
3687 TestCompletionCallback callback;
3688
3689 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463690 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]a796bcec2010-03-22 17:17:263691 std::string allgroups = tcp_conn_pool->last_group_name_received() +
3692 socks_conn_pool->last_group_name_received();
3693 EXPECT_EQ(tests[i].expected_group_name, allgroups);
[email protected]04e5be32009-06-26 20:00:313694 }
3695}
3696
[email protected]9172a982009-06-06 00:30:253697TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543698 SessionDependencies session_deps(
3699 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323700
[email protected]69719062010-01-05 20:09:213701 // This simulates failure resolving all hostnames; that means we will fail
3702 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:323703 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3704
[email protected]9172a982009-06-06 00:30:253705 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433706 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253707
3708 HttpRequestInfo request;
3709 request.method = "GET";
3710 request.url = GURL("http://www.google.com/");
3711
3712 TestCompletionCallback callback;
3713
[email protected]684970b2009-08-14 04:54:463714 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253715 EXPECT_EQ(ERR_IO_PENDING, rv);
3716
[email protected]9172a982009-06-06 00:30:253717 rv = callback.WaitForResult();
3718 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3719}
3720
[email protected]f3e6c1e2009-06-15 20:52:123721// Host resolution observer used by
3722// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3723// resovle requests are issued with a referrer of |expected_referrer|.
3724class ResolutionReferrerObserver : public HostResolver::Observer {
3725 public:
3726 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3727 : expected_referrer_(expected_referrer),
3728 called_start_with_referrer_(false),
3729 called_finish_with_referrer_(false) {
3730 }
3731
3732 virtual void OnStartResolution(int id,
3733 const HostResolver::RequestInfo& info) {
3734 if (info.referrer() == expected_referrer_)
3735 called_start_with_referrer_ = true;
3736 }
3737
3738 virtual void OnFinishResolutionWithStatus(
3739 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3740 if (info.referrer() == expected_referrer_)
3741 called_finish_with_referrer_ = true;
3742 }
3743
[email protected]eb255d32009-06-17 02:11:033744 virtual void OnCancelResolution(int id,
3745 const HostResolver::RequestInfo& info ) {
3746 FAIL() << "Should not be cancelling any requests!";
3747 }
3748
[email protected]f3e6c1e2009-06-15 20:52:123749 bool did_complete_with_expected_referrer() const {
3750 return called_start_with_referrer_ && called_finish_with_referrer_;
3751 }
3752
3753 private:
3754 GURL expected_referrer_;
3755 bool called_start_with_referrer_;
3756 bool called_finish_with_referrer_;
3757
3758 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3759};
3760
3761// Make sure that when HostResolver::Resolve() is invoked, it passes through
3762// the "referrer". This is depended on by the DNS prefetch observer.
3763TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3764 GURL referrer = GURL("http://expected-referrer/");
3765 EXPECT_TRUE(referrer.is_valid());
3766 ResolutionReferrerObserver resolution_observer(referrer);
3767
3768 SessionDependencies session_deps;
3769 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433770 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123771
3772 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143773 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123774
3775 // Connect up a mock socket which will fail when reading.
3776 MockRead data_reads[] = {
3777 MockRead(false, ERR_FAILED),
3778 };
[email protected]31a2bfe2010-02-09 08:03:393779 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593780 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:123781
3782 // Issue a request, containing an HTTP referrer.
3783 HttpRequestInfo request;
3784 request.method = "GET";
3785 request.referrer = referrer;
3786 request.url = GURL("http://www.google.com/");
3787
3788 // Run the request until it fails reading from the socket.
3789 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463790 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123791 EXPECT_EQ(ERR_IO_PENDING, rv);
3792 rv = callback.WaitForResult();
3793 EXPECT_EQ(ERR_FAILED, rv);
3794
3795 // Check that the host resolution observer saw |referrer|.
3796 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3797}
3798
[email protected]3b9cca42009-06-16 01:08:283799// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3800// host cache is bypassed.
3801TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3802 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323803
[email protected]a2c2fb92009-07-18 07:31:043804 // Select a host resolver that does caching.
3805 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323806
[email protected]3b9cca42009-06-16 01:08:283807 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433808 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:283809
3810 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3811 // a synchronous lookup.)
3812 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143813 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463814 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3815 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283816 EXPECT_EQ(OK, rv);
3817
3818 // Verify that it was added to host cache, by doing a subsequent async lookup
3819 // and confirming it completes synchronously.
3820 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463821 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283822 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463823 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323824 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283825
3826 // Inject a failure the next time that "www.google.com" is resolved. This way
3827 // we can tell if the next lookup hit the cache, or the "network".
3828 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323829 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283830
3831 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3832 // first read -- this won't be reached as the host resolution will fail first.
3833 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:393834 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593835 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:283836
3837 // Issue a request, asking to bypass the cache(s).
3838 HttpRequestInfo request;
3839 request.method = "GET";
3840 request.load_flags = LOAD_BYPASS_CACHE;
3841 request.url = GURL("http://www.google.com/");
3842
3843 // Run the request.
3844 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463845 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283846 ASSERT_EQ(ERR_IO_PENDING, rv);
3847 rv = callback.WaitForResult();
3848
3849 // If we bypassed the cache, we would have gotten a failure while resolving
3850 // "www.google.com".
3851 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3852}
3853
[email protected]0877e3d2009-10-17 22:29:573854// Make sure we can handle an error when writing the request.
3855TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3856 SessionDependencies session_deps;
3857 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3858
3859 HttpRequestInfo request;
3860 request.method = "GET";
3861 request.url = GURL("http://www.foo.com/");
3862 request.load_flags = 0;
3863
3864 MockWrite write_failure[] = {
3865 MockWrite(true, ERR_CONNECTION_RESET),
3866 };
[email protected]31a2bfe2010-02-09 08:03:393867 StaticSocketDataProvider data(NULL, 0,
3868 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:593869 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573870
3871 TestCompletionCallback callback;
3872
3873 scoped_ptr<HttpTransaction> trans(
3874 new HttpNetworkTransaction(CreateSession(&session_deps)));
3875
3876 int rv = trans->Start(&request, &callback, NULL);
3877 EXPECT_EQ(ERR_IO_PENDING, rv);
3878
3879 rv = callback.WaitForResult();
3880 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3881}
3882
3883// Check that a connection closed after the start of the headers finishes ok.
3884TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3885 SessionDependencies session_deps;
3886 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3887
3888 HttpRequestInfo request;
3889 request.method = "GET";
3890 request.url = GURL("http://www.foo.com/");
3891 request.load_flags = 0;
3892
3893 MockRead data_reads[] = {
3894 MockRead("HTTP/1."),
3895 MockRead(false, OK),
3896 };
3897
[email protected]31a2bfe2010-02-09 08:03:393898 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593899 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573900
3901 TestCompletionCallback callback;
3902
3903 scoped_ptr<HttpTransaction> trans(
3904 new HttpNetworkTransaction(CreateSession(&session_deps)));
3905
3906 int rv = trans->Start(&request, &callback, NULL);
3907 EXPECT_EQ(ERR_IO_PENDING, rv);
3908
3909 rv = callback.WaitForResult();
3910 EXPECT_EQ(OK, rv);
3911
3912 const HttpResponseInfo* response = trans->GetResponseInfo();
3913 EXPECT_TRUE(response != NULL);
3914
3915 EXPECT_TRUE(response->headers != NULL);
3916 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
3917
3918 std::string response_data;
3919 rv = ReadTransaction(trans.get(), &response_data);
3920 EXPECT_EQ(OK, rv);
3921 EXPECT_EQ("", response_data);
3922}
3923
3924// Make sure that a dropped connection while draining the body for auth
3925// restart does the right thing.
3926TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
3927 SessionDependencies session_deps;
3928 scoped_ptr<HttpTransaction> trans(
3929 new HttpNetworkTransaction(CreateSession(&session_deps)));
3930
3931 HttpRequestInfo request;
3932 request.method = "GET";
3933 request.url = GURL("http://www.google.com/");
3934 request.load_flags = 0;
3935
3936 MockWrite data_writes1[] = {
3937 MockWrite("GET / HTTP/1.1\r\n"
3938 "Host: www.google.com\r\n"
3939 "Connection: keep-alive\r\n\r\n"),
3940 };
3941
3942 MockRead data_reads1[] = {
3943 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3944 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3945 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3946 MockRead("Content-Length: 14\r\n\r\n"),
3947 MockRead("Unauth"),
3948 MockRead(true, ERR_CONNECTION_RESET),
3949 };
3950
[email protected]31a2bfe2010-02-09 08:03:393951 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3952 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593953 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:573954
3955 // After calling trans->RestartWithAuth(), this is the request we should
3956 // be issuing -- the final header line contains the credentials.
3957 MockWrite data_writes2[] = {
3958 MockWrite("GET / HTTP/1.1\r\n"
3959 "Host: www.google.com\r\n"
3960 "Connection: keep-alive\r\n"
3961 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3962 };
3963
3964 // Lastly, the server responds with the actual content.
3965 MockRead data_reads2[] = {
3966 MockRead("HTTP/1.1 200 OK\r\n"),
3967 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3968 MockRead("Content-Length: 100\r\n\r\n"),
3969 MockRead(false, OK),
3970 };
3971
[email protected]31a2bfe2010-02-09 08:03:393972 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3973 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593974 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:573975
3976 TestCompletionCallback callback1;
3977
3978 int rv = trans->Start(&request, &callback1, NULL);
3979 EXPECT_EQ(ERR_IO_PENDING, rv);
3980
3981 rv = callback1.WaitForResult();
3982 EXPECT_EQ(OK, rv);
3983
3984 const HttpResponseInfo* response = trans->GetResponseInfo();
3985 EXPECT_FALSE(response == NULL);
3986
3987 // The password prompt info should have been set in response->auth_challenge.
3988 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3989
3990 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3991 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3992 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3993
3994 TestCompletionCallback callback2;
3995
3996 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3997 EXPECT_EQ(ERR_IO_PENDING, rv);
3998
3999 rv = callback2.WaitForResult();
4000 EXPECT_EQ(OK, rv);
4001
4002 response = trans->GetResponseInfo();
4003 EXPECT_FALSE(response == NULL);
4004 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4005 EXPECT_EQ(100, response->headers->GetContentLength());
4006}
4007
4008// Test HTTPS connections going through a proxy that sends extra data.
4009TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4010 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4011
4012 HttpRequestInfo request;
4013 request.method = "GET";
4014 request.url = GURL("https://www.google.com/");
4015 request.load_flags = 0;
4016
4017 MockRead proxy_reads[] = {
4018 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4019 MockRead(false, OK)
4020 };
4021
[email protected]31a2bfe2010-02-09 08:03:394022 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594023 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574024
[email protected]5ecc992a42009-11-11 01:41:594025 session_deps.socket_factory.AddSocketDataProvider(&data);
4026 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574027
4028 TestCompletionCallback callback;
4029
4030 session_deps.socket_factory.ResetNextMockIndexes();
4031
4032 scoped_ptr<HttpTransaction> trans(
4033 new HttpNetworkTransaction(CreateSession(&session_deps)));
4034
4035 int rv = trans->Start(&request, &callback, NULL);
4036 EXPECT_EQ(ERR_IO_PENDING, rv);
4037
4038 rv = callback.WaitForResult();
4039 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4040}
4041
[email protected]e22e1362009-11-23 21:31:124042TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464043 SessionDependencies session_deps;
4044 scoped_ptr<HttpTransaction> trans(
4045 new HttpNetworkTransaction(CreateSession(&session_deps)));
4046
4047 HttpRequestInfo request;
4048 request.method = "GET";
4049 request.url = GURL("http://www.google.com/");
4050 request.load_flags = 0;
4051
[email protected]e22e1362009-11-23 21:31:124052 MockRead data_reads[] = {
4053 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4054 MockRead(false, OK),
4055 };
[email protected]9492e4a2010-02-24 00:58:464056
4057 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4058 session_deps.socket_factory.AddSocketDataProvider(&data);
4059
4060 TestCompletionCallback callback;
4061
4062 int rv = trans->Start(&request, &callback, NULL);
4063 EXPECT_EQ(ERR_IO_PENDING, rv);
4064
4065 EXPECT_EQ(OK, callback.WaitForResult());
4066
4067 const HttpResponseInfo* response = trans->GetResponseInfo();
4068 EXPECT_TRUE(response != NULL);
4069
4070 EXPECT_TRUE(response->headers != NULL);
4071 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4072
4073 std::string response_data;
4074 rv = ReadTransaction(trans.get(), &response_data);
4075 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124076}
4077
[email protected]95d88ffe2010-02-04 21:25:334078TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4079 SessionDependencies session_deps;
4080 scoped_ptr<HttpTransaction> trans(
4081 new HttpNetworkTransaction(CreateSession(&session_deps)));
4082
4083 HttpRequestInfo request;
4084 request.method = "POST";
4085 request.url = GURL("http://www.google.com/upload");
4086 request.upload_data = new UploadData;
4087 request.load_flags = 0;
4088
4089 FilePath temp_file_path;
4090 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4091 const uint64 kFakeSize = 100000; // file is actually blank
4092
4093 std::vector<UploadData::Element> elements;
4094 UploadData::Element element;
4095 element.SetToFilePath(temp_file_path);
4096 element.SetContentLength(kFakeSize);
4097 elements.push_back(element);
4098 request.upload_data->set_elements(elements);
4099 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4100
4101 MockRead data_reads[] = {
4102 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4103 MockRead("hello world"),
4104 MockRead(false, OK),
4105 };
[email protected]31a2bfe2010-02-09 08:03:394106 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334107 session_deps.socket_factory.AddSocketDataProvider(&data);
4108
4109 TestCompletionCallback callback;
4110
4111 int rv = trans->Start(&request, &callback, NULL);
4112 EXPECT_EQ(ERR_IO_PENDING, rv);
4113
4114 rv = callback.WaitForResult();
4115 EXPECT_EQ(OK, rv);
4116
4117 const HttpResponseInfo* response = trans->GetResponseInfo();
4118 EXPECT_TRUE(response != NULL);
4119
4120 EXPECT_TRUE(response->headers != NULL);
4121 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4122
4123 std::string response_data;
4124 rv = ReadTransaction(trans.get(), &response_data);
4125 EXPECT_EQ(OK, rv);
4126 EXPECT_EQ("hello world", response_data);
4127
4128 file_util::Delete(temp_file_path, false);
4129}
4130
[email protected]aeefc9e82010-02-19 16:18:274131// Tests that changes to Auth realms are treated like auth rejections.
4132TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4133 SessionDependencies session_deps;
4134 scoped_ptr<HttpTransaction> trans(
4135 new HttpNetworkTransaction(CreateSession(&session_deps)));
4136
4137 HttpRequestInfo request;
4138 request.method = "GET";
4139 request.url = GURL("http://www.google.com/");
4140 request.load_flags = 0;
4141
4142 // First transaction will request a resource and receive a Basic challenge
4143 // with realm="first_realm".
4144 MockWrite data_writes1[] = {
4145 MockWrite("GET / HTTP/1.1\r\n"
4146 "Host: www.google.com\r\n"
4147 "Connection: keep-alive\r\n"
4148 "\r\n"),
4149 };
4150 MockRead data_reads1[] = {
4151 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4152 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4153 "\r\n"),
4154 };
4155
4156 // After calling trans->RestartWithAuth(), provide an Authentication header
4157 // for first_realm. The server will reject and provide a challenge with
4158 // second_realm.
4159 MockWrite data_writes2[] = {
4160 MockWrite("GET / HTTP/1.1\r\n"
4161 "Host: www.google.com\r\n"
4162 "Connection: keep-alive\r\n"
4163 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4164 "\r\n"),
4165 };
4166 MockRead data_reads2[] = {
4167 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4168 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4169 "\r\n"),
4170 };
4171
4172 // This again fails, and goes back to first_realm. Make sure that the
4173 // entry is removed from cache.
4174 MockWrite data_writes3[] = {
4175 MockWrite("GET / HTTP/1.1\r\n"
4176 "Host: www.google.com\r\n"
4177 "Connection: keep-alive\r\n"
4178 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4179 "\r\n"),
4180 };
4181 MockRead data_reads3[] = {
4182 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4183 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4184 "\r\n"),
4185 };
4186
4187 // Try one last time (with the correct password) and get the resource.
4188 MockWrite data_writes4[] = {
4189 MockWrite("GET / HTTP/1.1\r\n"
4190 "Host: www.google.com\r\n"
4191 "Connection: keep-alive\r\n"
4192 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4193 "\r\n"),
4194 };
4195 MockRead data_reads4[] = {
4196 MockRead("HTTP/1.1 200 OK\r\n"
4197 "Content-Type: text/html; charset=iso-8859-1\r\n"
4198 "Content-Length: 100\r\n"
4199 "\r\n"),
4200 };
4201
4202 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4203 data_writes1, arraysize(data_writes1));
4204 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4205 data_writes2, arraysize(data_writes2));
4206 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4207 data_writes3, arraysize(data_writes3));
4208 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4209 data_writes4, arraysize(data_writes4));
4210 session_deps.socket_factory.AddSocketDataProvider(&data1);
4211 session_deps.socket_factory.AddSocketDataProvider(&data2);
4212 session_deps.socket_factory.AddSocketDataProvider(&data3);
4213 session_deps.socket_factory.AddSocketDataProvider(&data4);
4214
4215 TestCompletionCallback callback1;
4216
4217 // Issue the first request with Authorize headers. There should be a
4218 // password prompt for first_realm waiting to be filled in after the
4219 // transaction completes.
4220 int rv = trans->Start(&request, &callback1, NULL);
4221 EXPECT_EQ(ERR_IO_PENDING, rv);
4222 rv = callback1.WaitForResult();
4223 EXPECT_EQ(OK, rv);
4224 const HttpResponseInfo* response = trans->GetResponseInfo();
4225 ASSERT_FALSE(response == NULL);
4226 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4227 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4228 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4229 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4230
4231 // Issue the second request with an incorrect password. There should be a
4232 // password prompt for second_realm waiting to be filled in after the
4233 // transaction completes.
4234 TestCompletionCallback callback2;
4235 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4236 EXPECT_EQ(ERR_IO_PENDING, rv);
4237 rv = callback2.WaitForResult();
4238 EXPECT_EQ(OK, rv);
4239 response = trans->GetResponseInfo();
4240 ASSERT_FALSE(response == NULL);
4241 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4242 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4243 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4244 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4245
4246 // Issue the third request with another incorrect password. There should be
4247 // a password prompt for first_realm waiting to be filled in. If the password
4248 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4249 // first_realm was not correctly removed.
4250 TestCompletionCallback callback3;
4251 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4252 EXPECT_EQ(ERR_IO_PENDING, rv);
4253 rv = callback3.WaitForResult();
4254 EXPECT_EQ(OK, rv);
4255 response = trans->GetResponseInfo();
4256 ASSERT_FALSE(response == NULL);
4257 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4258 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4259 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4260 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4261
4262 // Issue the fourth request with the correct password and username.
4263 TestCompletionCallback callback4;
4264 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4265 EXPECT_EQ(ERR_IO_PENDING, rv);
4266 rv = callback4.WaitForResult();
4267 EXPECT_EQ(OK, rv);
4268 response = trans->GetResponseInfo();
4269 ASSERT_FALSE(response == NULL);
4270 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4271}
4272
[email protected]564b4912010-03-09 16:30:424273TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424274 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
4275
[email protected]564b4912010-03-09 16:30:424276 SessionDependencies session_deps;
4277
4278 MockRead data_reads[] = {
4279 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]a2cb8122010-03-10 17:22:424280 MockRead("Alternate-Protocol: 443:npn-spdy\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424281 MockRead("hello world"),
4282 MockRead(false, OK),
4283 };
4284
4285 HttpRequestInfo request;
4286 request.method = "GET";
4287 request.url = GURL("http://www.google.com/");
4288 request.load_flags = 0;
4289
4290 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4291
4292 session_deps.socket_factory.AddSocketDataProvider(&data);
4293
4294 TestCompletionCallback callback;
4295
4296 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4297 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4298
4299 int rv = trans->Start(&request, &callback, NULL);
4300 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534301
[email protected]564b4912010-03-09 16:30:424302 HostPortPair http_host_port_pair;
4303 http_host_port_pair.host = "www.google.com";
4304 http_host_port_pair.port = 80;
4305 const HttpAlternateProtocols& alternate_protocols =
4306 session->alternate_protocols();
4307 EXPECT_FALSE(
4308 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4309
4310 EXPECT_EQ(OK, callback.WaitForResult());
4311
4312 const HttpResponseInfo* response = trans->GetResponseInfo();
4313 ASSERT_TRUE(response != NULL);
4314 ASSERT_TRUE(response->headers != NULL);
4315 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4316
4317 std::string response_data;
4318 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4319 EXPECT_EQ("hello world", response_data);
4320
4321 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4322 const HttpAlternateProtocols::PortProtocolPair alternate =
4323 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4324 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4325 expected_alternate.port = 443;
[email protected]a2cb8122010-03-10 17:22:424326 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY;
[email protected]564b4912010-03-09 16:30:424327 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424328
4329 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424330}
4331
4332TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
4333 SessionDependencies session_deps;
4334
4335 HttpRequestInfo request;
4336 request.method = "GET";
4337 request.url = GURL("http://www.google.com/");
4338 request.load_flags = 0;
4339
4340 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4341 StaticSocketDataProvider first_data;
4342 first_data.set_connect_data(mock_connect);
4343 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4344
4345 MockRead data_reads[] = {
4346 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4347 MockRead("hello world"),
4348 MockRead(true, OK),
4349 };
4350 StaticSocketDataProvider second_data(
4351 data_reads, arraysize(data_reads), NULL, 0);
4352 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4353
4354 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4355 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4356 // http://crbug.com/37454.
4357 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4358
4359 TestCompletionCallback callback;
4360
4361 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4362
4363 HostPortPair http_host_port_pair;
4364 http_host_port_pair.host = "www.google.com";
4365 http_host_port_pair.port = 80;
4366 HttpAlternateProtocols* alternate_protocols =
4367 session->mutable_alternate_protocols();
4368 alternate_protocols->SetAlternateProtocolFor(
4369 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]a2cb8122010-03-10 17:22:424370 HttpAlternateProtocols::NPN_SPDY);
[email protected]564b4912010-03-09 16:30:424371
4372 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4373
4374 int rv = trans->Start(&request, &callback, NULL);
4375 EXPECT_EQ(ERR_IO_PENDING, rv);
4376 EXPECT_EQ(OK, callback.WaitForResult());
4377
4378 const HttpResponseInfo* response = trans->GetResponseInfo();
4379 ASSERT_TRUE(response != NULL);
4380 ASSERT_TRUE(response->headers != NULL);
4381 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4382
4383 std::string response_data;
4384 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4385 EXPECT_EQ("hello world", response_data);
4386
4387 ASSERT_TRUE(
4388 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
4389 const HttpAlternateProtocols::PortProtocolPair alternate =
4390 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
4391 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
4392}
4393
4394// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
4395// says that it does SPDY, but it just does the TLS handshake, but the NPN
4396// response does not indicate SPDY, so we just do standard HTTPS over the port.
4397// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
4398// on the original port.
[email protected]a2cb8122010-03-10 17:22:424399// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
4400// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:534401//
[email protected]a2cb8122010-03-10 17:22:424402// HttpRequestInfo request;
4403// request.method = "GET";
4404// request.url = GURL("http://www.google.com/");
4405// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:534406//
[email protected]a2cb8122010-03-10 17:22:424407// MockRead data_reads[] = {
4408// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4409// MockRead("hello world"),
4410// MockRead(true, OK),
4411// };
4412// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4413// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:534414//
[email protected]a2cb8122010-03-10 17:22:424415// SSLSocketDataProvider ssl(true, OK);
4416// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:534417//
[email protected]a2cb8122010-03-10 17:22:424418// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:534419//
[email protected]a2cb8122010-03-10 17:22:424420// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:534421//
[email protected]a2cb8122010-03-10 17:22:424422// HostPortPair http_host_port_pair;
4423// http_host_port_pair.host = "www.google.com";
4424// http_host_port_pair.port = 80;
4425// HttpAlternateProtocols* alternate_protocols =
4426// session->mutable_alternate_protocols();
4427// alternate_protocols->SetAlternateProtocolFor(
4428// http_host_port_pair, 1234 /* port is ignored */,
4429// HttpAlternateProtocols::NPN_SPDY);
[email protected]9e743cd2010-03-16 07:03:534430//
[email protected]a2cb8122010-03-10 17:22:424431// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:534432//
[email protected]a2cb8122010-03-10 17:22:424433// int rv = trans->Start(&request, &callback, NULL);
4434// EXPECT_EQ(ERR_IO_PENDING, rv);
4435// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:534436//
[email protected]a2cb8122010-03-10 17:22:424437// const HttpResponseInfo* response = trans->GetResponseInfo();
4438// ASSERT_TRUE(response != NULL);
4439// ASSERT_TRUE(response->headers != NULL);
4440// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:534441//
[email protected]a2cb8122010-03-10 17:22:424442// std::string response_data;
4443// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4444// EXPECT_EQ("hello world", response_data);
4445// }
4446
4447TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]564b4912010-03-09 16:30:424448 SessionDependencies session_deps;
4449
4450 HttpRequestInfo request;
4451 request.method = "GET";
4452 request.url = GURL("http://www.google.com/");
4453 request.load_flags = 0;
4454
[email protected]a2cb8122010-03-10 17:22:424455 StaticSocketDataProvider first_tcp_connect;
4456 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
4457
4458 SSLSocketDataProvider ssl(true, OK);
4459 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4460
[email protected]564b4912010-03-09 16:30:424461 MockRead data_reads[] = {
4462 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4463 MockRead("hello world"),
4464 MockRead(true, OK),
4465 };
[email protected]a2cb8122010-03-10 17:22:424466 StaticSocketDataProvider fallback_data(
4467 data_reads, arraysize(data_reads), NULL, 0);
4468 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:424469
4470 TestCompletionCallback callback;
4471
4472 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4473
4474 HostPortPair http_host_port_pair;
4475 http_host_port_pair.host = "www.google.com";
4476 http_host_port_pair.port = 80;
4477 HttpAlternateProtocols* alternate_protocols =
4478 session->mutable_alternate_protocols();
4479 alternate_protocols->SetAlternateProtocolFor(
4480 http_host_port_pair, 1234 /* port is ignored */,
[email protected]a2cb8122010-03-10 17:22:424481 HttpAlternateProtocols::NPN_SPDY);
[email protected]564b4912010-03-09 16:30:424482
4483 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4484
4485 int rv = trans->Start(&request, &callback, NULL);
4486 EXPECT_EQ(ERR_IO_PENDING, rv);
4487 EXPECT_EQ(OK, callback.WaitForResult());
4488
4489 const HttpResponseInfo* response = trans->GetResponseInfo();
4490 ASSERT_TRUE(response != NULL);
4491 ASSERT_TRUE(response->headers != NULL);
4492 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4493
4494 std::string response_data;
4495 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4496 EXPECT_EQ("hello world", response_data);
4497}
4498
[email protected]89ceba9a2009-03-21 03:46:064499} // namespace net