blob: 1cdc8187626e7fbab9a2a5b6297249234afbbfb8 [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]a937a06d2009-08-19 21:19:24185class CaptureGroupNameSocketPool : public TCPClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31186 public:
[email protected]100d5fb92009-12-21 21:08:35187 CaptureGroupNameSocketPool() : TCPClientSocketPool(0, 0, NULL, NULL, NULL) {}
[email protected]d80a4322009-08-14 07:07:49188 const std::string last_group_name_received() const {
189 return last_group_name_;
190 }
191
[email protected]684970b2009-08-14 04:54:46192 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49193 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31194 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31195 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46196 CompletionCallback* callback,
197 LoadLog* load_log) {
[email protected]04e5be32009-06-26 20:00:31198 last_group_name_ = group_name;
199 return ERR_IO_PENDING;
200 }
[email protected]04e5be32009-06-26 20:00:31201 virtual void CancelRequest(const std::string& group_name,
202 const ClientSocketHandle* handle) { }
203 virtual void ReleaseSocket(const std::string& group_name,
204 ClientSocket* socket) {}
205 virtual void CloseIdleSockets() {}
206 virtual HostResolver* GetHostResolver() const {
207 return NULL;
208 }
209 virtual int IdleSocketCount() const {
210 return 0;
211 }
212 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
213 return 0;
214 }
215 virtual LoadState GetLoadState(const std::string& group_name,
216 const ClientSocketHandle* handle) const {
217 return LOAD_STATE_IDLE;
218 }
[email protected]d80a4322009-08-14 07:07:49219
220 private:
[email protected]04e5be32009-06-26 20:00:31221 std::string last_group_name_;
222};
223
[email protected]231d5a32008-09-13 00:45:27224//-----------------------------------------------------------------------------
225
226TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59227 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40228 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43229 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27230}
231
232TEST_F(HttpNetworkTransactionTest, SimpleGET) {
233 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35234 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
235 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42236 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27237 };
[email protected]31a2bfe2010-02-09 08:03:39238 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
239 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42240 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27241 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
242 EXPECT_EQ("hello world", out.response_data);
243}
244
245// Response with no status line.
246TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
247 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35248 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42249 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27250 };
[email protected]31a2bfe2010-02-09 08:03:39251 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
252 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42253 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27254 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
255 EXPECT_EQ("hello world", out.response_data);
256}
257
258// Allow up to 4 bytes of junk to precede status line.
259TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
260 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35261 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42262 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27263 };
[email protected]31a2bfe2010-02-09 08:03:39264 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
265 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42266 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27267 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
268 EXPECT_EQ("DATA", out.response_data);
269}
270
271// Allow up to 4 bytes of junk to precede status line.
272TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
273 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35274 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42275 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27276 };
[email protected]31a2bfe2010-02-09 08:03:39277 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
278 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42279 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27280 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
281 EXPECT_EQ("DATA", out.response_data);
282}
283
284// Beyond 4 bytes of slop and it should fail to find a status line.
285TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
286 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35287 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42288 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27289 };
[email protected]31a2bfe2010-02-09 08:03:39290 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
291 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42292 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25293 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
294 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27295}
296
297// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
298TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
299 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35300 MockRead("\n"),
301 MockRead("\n"),
302 MockRead("Q"),
303 MockRead("J"),
304 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42305 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27306 };
[email protected]31a2bfe2010-02-09 08:03:39307 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
308 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42309 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27310 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
311 EXPECT_EQ("DATA", out.response_data);
312}
313
314// Close the connection before enough bytes to have a status line.
315TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
316 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35317 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42318 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27319 };
[email protected]31a2bfe2010-02-09 08:03:39320 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
321 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42322 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27323 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
324 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52325}
326
[email protected]f9d44aa2008-09-23 23:57:17327// Simulate a 204 response, lacking a Content-Length header, sent over a
328// persistent connection. The response should still terminate since a 204
329// cannot have a response body.
330TEST_F(HttpNetworkTransactionTest, StopsReading204) {
331 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35332 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
333 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42334 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17335 };
[email protected]31a2bfe2010-02-09 08:03:39336 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
337 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42338 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17339 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
340 EXPECT_EQ("", out.response_data);
341}
342
[email protected]0877e3d2009-10-17 22:29:57343// A simple request using chunked encoding with some extra data after.
344// (Like might be seen in a pipelined response.)
345TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
346 MockRead data_reads[] = {
347 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
348 MockRead("5\r\nHello\r\n"),
349 MockRead("1\r\n"),
350 MockRead(" \r\n"),
351 MockRead("5\r\nworld\r\n"),
352 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
353 MockRead(false, OK),
354 };
[email protected]31a2bfe2010-02-09 08:03:39355 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
356 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57357 EXPECT_EQ(OK, out.rv);
358 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
359 EXPECT_EQ("Hello world", out.response_data);
360}
361
[email protected]ef0faf2e72009-03-05 23:27:23362// Do a request using the HEAD method. Verify that we don't try to read the
363// message body (since HEAD has none).
364TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59365 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40366 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43367 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23368
[email protected]1c773ea12009-04-28 19:58:42369 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23370 request.method = "HEAD";
371 request.url = GURL("http://www.google.com/");
372 request.load_flags = 0;
373
374 MockWrite data_writes1[] = {
375 MockWrite("HEAD / HTTP/1.1\r\n"
376 "Host: www.google.com\r\n"
377 "Connection: keep-alive\r\n"
378 "Content-Length: 0\r\n\r\n"),
379 };
380 MockRead data_reads1[] = {
381 MockRead("HTTP/1.1 404 Not Found\r\n"),
382 MockRead("Server: Blah\r\n"),
383 MockRead("Content-Length: 1234\r\n\r\n"),
384
385 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42386 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23387 };
388
[email protected]31a2bfe2010-02-09 08:03:39389 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
390 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59391 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23392
393 TestCompletionCallback callback1;
394
[email protected]684970b2009-08-14 04:54:46395 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42396 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23397
398 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42399 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23400
[email protected]1c773ea12009-04-28 19:58:42401 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23402 EXPECT_FALSE(response == NULL);
403
404 // Check that the headers got parsed.
405 EXPECT_TRUE(response->headers != NULL);
406 EXPECT_EQ(1234, response->headers->GetContentLength());
407 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
408
409 std::string server_header;
410 void* iter = NULL;
411 bool has_server_header = response->headers->EnumerateHeader(
412 &iter, "Server", &server_header);
413 EXPECT_TRUE(has_server_header);
414 EXPECT_EQ("Blah", server_header);
415
416 // Reading should give EOF right away, since there is no message body
417 // (despite non-zero content-length).
418 std::string response_data;
419 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42420 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23421 EXPECT_EQ("", response_data);
422}
423
initial.commit586acc5fe2008-07-26 22:42:52424TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59425 SessionDependencies session_deps;
426 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52427
428 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35429 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
430 MockRead("hello"),
431 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
432 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42433 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52434 };
[email protected]31a2bfe2010-02-09 08:03:39435 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59436 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52437
438 const char* kExpectedResponseData[] = {
439 "hello", "world"
440 };
441
442 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43443 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52444
[email protected]1c773ea12009-04-28 19:58:42445 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52446 request.method = "GET";
447 request.url = GURL("http://www.google.com/");
448 request.load_flags = 0;
449
450 TestCompletionCallback callback;
451
[email protected]684970b2009-08-14 04:54:46452 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42453 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52454
455 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42456 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52457
[email protected]1c773ea12009-04-28 19:58:42458 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52459 EXPECT_TRUE(response != NULL);
460
461 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25462 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52463
464 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57465 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42466 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25467 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52468 }
469}
470
471TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59472 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40473 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43474 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52475
[email protected]1c773ea12009-04-28 19:58:42476 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52477 request.method = "POST";
478 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42479 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52480 request.upload_data->AppendBytes("foo", 3);
481 request.load_flags = 0;
482
483 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35484 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
485 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
486 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42487 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52488 };
[email protected]31a2bfe2010-02-09 08:03:39489 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59490 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52491
492 TestCompletionCallback callback;
493
[email protected]684970b2009-08-14 04:54:46494 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42495 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52496
497 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42498 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52499
[email protected]1c773ea12009-04-28 19:58:42500 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52501 EXPECT_TRUE(response != NULL);
502
503 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25504 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52505
506 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57507 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42508 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25509 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52510}
511
[email protected]3a2d3662009-03-27 03:49:14512// This test is almost the same as Ignores100 above, but the response contains
513// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57514// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14515TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59516 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40517 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43518 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14519
[email protected]1c773ea12009-04-28 19:58:42520 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14521 request.method = "GET";
522 request.url = GURL("http://www.foo.com/");
523 request.load_flags = 0;
524
525 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57526 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
527 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14528 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42529 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14530 };
[email protected]31a2bfe2010-02-09 08:03:39531 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59532 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14533
534 TestCompletionCallback callback;
535
[email protected]684970b2009-08-14 04:54:46536 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42537 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14538
539 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42540 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14541
[email protected]1c773ea12009-04-28 19:58:42542 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14543 EXPECT_TRUE(response != NULL);
544
545 EXPECT_TRUE(response->headers != NULL);
546 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
547
548 std::string response_data;
549 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42550 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14551 EXPECT_EQ("hello world", response_data);
552}
553
[email protected]ee9410e72010-01-07 01:42:38554TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
555 SessionDependencies session_deps;
556 scoped_ptr<HttpTransaction> trans(
557 new HttpNetworkTransaction(CreateSession(&session_deps)));
558
559 HttpRequestInfo request;
560 request.method = "POST";
561 request.url = GURL("http://www.foo.com/");
562 request.load_flags = 0;
563
564 MockRead data_reads[] = {
565 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
566 MockRead(true, 0),
567 };
[email protected]31a2bfe2010-02-09 08:03:39568 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38569 session_deps.socket_factory.AddSocketDataProvider(&data);
570
571 TestCompletionCallback callback;
572
573 int rv = trans->Start(&request, &callback, NULL);
574 EXPECT_EQ(ERR_IO_PENDING, rv);
575
576 rv = callback.WaitForResult();
577 EXPECT_EQ(OK, rv);
578
579 std::string response_data;
580 rv = ReadTransaction(trans.get(), &response_data);
581 EXPECT_EQ(OK, rv);
582 EXPECT_EQ("", response_data);
583}
584
585TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
586 SessionDependencies session_deps;
587 scoped_ptr<HttpTransaction> trans(
588 new HttpNetworkTransaction(CreateSession(&session_deps)));
589
590 HttpRequestInfo request;
591 request.method = "POST";
592 request.url = GURL("http://www.foo.com/");
593 request.load_flags = 0;
594
595 MockRead data_reads[] = {
596 MockRead(true, 0),
597 };
[email protected]31a2bfe2010-02-09 08:03:39598 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38599 session_deps.socket_factory.AddSocketDataProvider(&data);
600
601 TestCompletionCallback callback;
602
603 int rv = trans->Start(&request, &callback, NULL);
604 EXPECT_EQ(ERR_IO_PENDING, rv);
605
606 rv = callback.WaitForResult();
607 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
608}
609
[email protected]3d2a59b2008-09-26 19:44:25610// read_failure specifies a read failure that should cause the network
611// transaction to resend the request.
612void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
613 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59614 SessionDependencies session_deps;
615 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52616
[email protected]1c773ea12009-04-28 19:58:42617 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52618 request.method = "GET";
619 request.url = GURL("http://www.foo.com/");
620 request.load_flags = 0;
621
622 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35623 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
624 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25625 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52626 };
[email protected]31a2bfe2010-02-09 08:03:39627 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59628 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52629
630 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35631 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
632 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42633 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52634 };
[email protected]31a2bfe2010-02-09 08:03:39635 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59636 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52637
638 const char* kExpectedResponseData[] = {
639 "hello", "world"
640 };
641
642 for (int i = 0; i < 2; ++i) {
643 TestCompletionCallback callback;
644
[email protected]5695b8c2009-09-30 21:36:43645 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52646
[email protected]684970b2009-08-14 04:54:46647 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42648 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52649
650 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42651 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52652
[email protected]1c773ea12009-04-28 19:58:42653 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52654 EXPECT_TRUE(response != NULL);
655
656 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25657 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52658
659 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57660 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42661 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25662 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52663 }
664}
[email protected]3d2a59b2008-09-26 19:44:25665
666TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42667 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25668 KeepAliveConnectionResendRequestTest(read_failure);
669}
670
671TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42672 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25673 KeepAliveConnectionResendRequestTest(read_failure);
674}
675
676TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59677 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40678 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43679 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25680
[email protected]1c773ea12009-04-28 19:58:42681 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25682 request.method = "GET";
683 request.url = GURL("http://www.google.com/");
684 request.load_flags = 0;
685
686 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42687 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35688 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
689 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42690 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25691 };
[email protected]31a2bfe2010-02-09 08:03:39692 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59693 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25694
695 TestCompletionCallback callback;
696
[email protected]684970b2009-08-14 04:54:46697 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42698 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25699
700 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42701 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25702
[email protected]1c773ea12009-04-28 19:58:42703 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25704 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25705}
706
707// What do various browsers do when the server closes a non-keepalive
708// connection without sending any response header or body?
709//
710// IE7: error page
711// Safari 3.1.2 (Windows): error page
712// Firefox 3.0.1: blank page
713// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42714// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
715// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25716TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
717 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42718 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35719 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
720 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42721 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25722 };
[email protected]31a2bfe2010-02-09 08:03:39723 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
724 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42725 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25726}
[email protected]038e9a32008-10-08 22:40:16727
728// Test the request-challenge-retry sequence for basic auth.
729// (basic auth is the easiest to mock, because it has no randomness).
730TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59731 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40732 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43733 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16734
[email protected]1c773ea12009-04-28 19:58:42735 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16736 request.method = "GET";
737 request.url = GURL("http://www.google.com/");
738 request.load_flags = 0;
739
[email protected]f9ee6b52008-11-08 06:46:23740 MockWrite data_writes1[] = {
741 MockWrite("GET / HTTP/1.1\r\n"
742 "Host: www.google.com\r\n"
743 "Connection: keep-alive\r\n\r\n"),
744 };
745
[email protected]038e9a32008-10-08 22:40:16746 MockRead data_reads1[] = {
747 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
748 // Give a couple authenticate options (only the middle one is actually
749 // supported).
[email protected]22927ad2009-09-21 19:56:19750 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16751 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
752 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
753 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
754 // Large content-length -- won't matter, as connection will be reset.
755 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42756 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16757 };
758
759 // After calling trans->RestartWithAuth(), this is the request we should
760 // be issuing -- the final header line contains the credentials.
761 MockWrite data_writes2[] = {
762 MockWrite("GET / HTTP/1.1\r\n"
763 "Host: www.google.com\r\n"
764 "Connection: keep-alive\r\n"
765 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
766 };
767
768 // Lastly, the server responds with the actual content.
769 MockRead data_reads2[] = {
770 MockRead("HTTP/1.0 200 OK\r\n"),
771 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
772 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42773 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16774 };
775
[email protected]31a2bfe2010-02-09 08:03:39776 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
777 data_writes1, arraysize(data_writes1));
778 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
779 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59780 session_deps.socket_factory.AddSocketDataProvider(&data1);
781 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16782
783 TestCompletionCallback callback1;
784
[email protected]684970b2009-08-14 04:54:46785 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42786 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16787
788 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42789 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16790
[email protected]1c773ea12009-04-28 19:58:42791 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16792 EXPECT_FALSE(response == NULL);
793
794 // The password prompt info should have been set in response->auth_challenge.
795 EXPECT_FALSE(response->auth_challenge.get() == NULL);
796
[email protected]71e4573a2009-05-21 22:03:00797 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16798 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
799 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
800
801 TestCompletionCallback callback2;
802
803 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42804 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16805
806 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42807 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16808
809 response = trans->GetResponseInfo();
810 EXPECT_FALSE(response == NULL);
811 EXPECT_TRUE(response->auth_challenge.get() == NULL);
812 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16813}
814
[email protected]861fcd52009-08-26 02:33:46815TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
816 SessionDependencies session_deps;
817 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43818 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46819
820 HttpRequestInfo request;
821 request.method = "GET";
822 request.url = GURL("http://www.google.com/");
823 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
824
825 MockWrite data_writes[] = {
826 MockWrite("GET / HTTP/1.1\r\n"
827 "Host: www.google.com\r\n"
828 "Connection: keep-alive\r\n\r\n"),
829 };
830
831 MockRead data_reads[] = {
832 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
833 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
834 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
835 // Large content-length -- won't matter, as connection will be reset.
836 MockRead("Content-Length: 10000\r\n\r\n"),
837 MockRead(false, ERR_FAILED),
838 };
839
[email protected]31a2bfe2010-02-09 08:03:39840 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
841 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59842 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46843 TestCompletionCallback callback;
844
845 int rv = trans->Start(&request, &callback, NULL);
846 EXPECT_EQ(ERR_IO_PENDING, rv);
847
848 rv = callback.WaitForResult();
849 EXPECT_EQ(0, rv);
850
851 const HttpResponseInfo* response = trans->GetResponseInfo();
852 ASSERT_FALSE(response == NULL);
853 EXPECT_TRUE(response->auth_challenge.get() == NULL);
854}
855
[email protected]2d2697f92009-02-18 21:00:32856// Test the request-challenge-retry sequence for basic auth, over a keep-alive
857// connection.
858TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59859 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40860 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43861 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32862
[email protected]1c773ea12009-04-28 19:58:42863 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32864 request.method = "GET";
865 request.url = GURL("http://www.google.com/");
866 request.load_flags = 0;
867
868 MockWrite data_writes1[] = {
869 MockWrite("GET / HTTP/1.1\r\n"
870 "Host: www.google.com\r\n"
871 "Connection: keep-alive\r\n\r\n"),
872
873 // After calling trans->RestartWithAuth(), this is the request we should
874 // be issuing -- the final header line contains the credentials.
875 MockWrite("GET / HTTP/1.1\r\n"
876 "Host: www.google.com\r\n"
877 "Connection: keep-alive\r\n"
878 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
879 };
880
881 MockRead data_reads1[] = {
882 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
883 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
884 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
885 MockRead("Content-Length: 14\r\n\r\n"),
886 MockRead("Unauthorized\r\n"),
887
888 // Lastly, the server responds with the actual content.
889 MockRead("HTTP/1.1 200 OK\r\n"),
890 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
891 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42892 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32893 };
894
[email protected]31a2bfe2010-02-09 08:03:39895 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
896 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59897 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32898
899 TestCompletionCallback callback1;
900
[email protected]684970b2009-08-14 04:54:46901 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42902 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32903
904 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42905 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32906
[email protected]1c773ea12009-04-28 19:58:42907 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32908 EXPECT_FALSE(response == NULL);
909
910 // The password prompt info should have been set in response->auth_challenge.
911 EXPECT_FALSE(response->auth_challenge.get() == NULL);
912
[email protected]71e4573a2009-05-21 22:03:00913 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32914 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
915 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
916
917 TestCompletionCallback callback2;
918
919 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42920 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32921
922 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42923 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32924
925 response = trans->GetResponseInfo();
926 EXPECT_FALSE(response == NULL);
927 EXPECT_TRUE(response->auth_challenge.get() == NULL);
928 EXPECT_EQ(100, response->headers->GetContentLength());
929}
930
931// Test the request-challenge-retry sequence for basic auth, over a keep-alive
932// connection and with no response body to drain.
933TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59934 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40935 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43936 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32937
[email protected]1c773ea12009-04-28 19:58:42938 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32939 request.method = "GET";
940 request.url = GURL("http://www.google.com/");
941 request.load_flags = 0;
942
943 MockWrite data_writes1[] = {
944 MockWrite("GET / HTTP/1.1\r\n"
945 "Host: www.google.com\r\n"
946 "Connection: keep-alive\r\n\r\n"),
947
948 // After calling trans->RestartWithAuth(), this is the request we should
949 // be issuing -- the final header line contains the credentials.
950 MockWrite("GET / HTTP/1.1\r\n"
951 "Host: www.google.com\r\n"
952 "Connection: keep-alive\r\n"
953 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
954 };
955
[email protected]2d2697f92009-02-18 21:00:32956 MockRead data_reads1[] = {
957 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
958 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:31959 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:32960
961 // Lastly, the server responds with the actual content.
962 MockRead("HTTP/1.1 200 OK\r\n"),
963 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
964 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42965 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32966 };
967
[email protected]31a2bfe2010-02-09 08:03:39968 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
969 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59970 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32971
972 TestCompletionCallback callback1;
973
[email protected]684970b2009-08-14 04:54:46974 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42975 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32976
977 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42978 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32979
[email protected]1c773ea12009-04-28 19:58:42980 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32981 EXPECT_FALSE(response == NULL);
982
983 // The password prompt info should have been set in response->auth_challenge.
984 EXPECT_FALSE(response->auth_challenge.get() == NULL);
985
[email protected]71e4573a2009-05-21 22:03:00986 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32987 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
988 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
989
990 TestCompletionCallback callback2;
991
992 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42993 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32994
995 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42996 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32997
998 response = trans->GetResponseInfo();
999 EXPECT_FALSE(response == NULL);
1000 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1001 EXPECT_EQ(100, response->headers->GetContentLength());
1002}
1003
1004// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1005// connection and with a large response body to drain.
1006TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591007 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401008 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431009 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321010
[email protected]1c773ea12009-04-28 19:58:421011 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321012 request.method = "GET";
1013 request.url = GURL("http://www.google.com/");
1014 request.load_flags = 0;
1015
1016 MockWrite data_writes1[] = {
1017 MockWrite("GET / HTTP/1.1\r\n"
1018 "Host: www.google.com\r\n"
1019 "Connection: keep-alive\r\n\r\n"),
1020
1021 // After calling trans->RestartWithAuth(), this is the request we should
1022 // be issuing -- the final header line contains the credentials.
1023 MockWrite("GET / HTTP/1.1\r\n"
1024 "Host: www.google.com\r\n"
1025 "Connection: keep-alive\r\n"
1026 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1027 };
1028
1029 // Respond with 5 kb of response body.
1030 std::string large_body_string("Unauthorized");
1031 large_body_string.append(5 * 1024, ' ');
1032 large_body_string.append("\r\n");
1033
1034 MockRead data_reads1[] = {
1035 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1036 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1037 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1038 // 5134 = 12 + 5 * 1024 + 2
1039 MockRead("Content-Length: 5134\r\n\r\n"),
1040 MockRead(true, large_body_string.data(), large_body_string.size()),
1041
1042 // Lastly, the server responds with the actual content.
1043 MockRead("HTTP/1.1 200 OK\r\n"),
1044 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1045 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421046 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321047 };
1048
[email protected]31a2bfe2010-02-09 08:03:391049 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1050 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591051 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321052
1053 TestCompletionCallback callback1;
1054
[email protected]684970b2009-08-14 04:54:461055 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421056 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321057
1058 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421059 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321060
[email protected]1c773ea12009-04-28 19:58:421061 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321062 EXPECT_FALSE(response == NULL);
1063
1064 // The password prompt info should have been set in response->auth_challenge.
1065 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1066
[email protected]71e4573a2009-05-21 22:03:001067 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321068 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1069 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1070
1071 TestCompletionCallback callback2;
1072
1073 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421074 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321075
1076 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421077 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321078
1079 response = trans->GetResponseInfo();
1080 EXPECT_FALSE(response == NULL);
1081 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1082 EXPECT_EQ(100, response->headers->GetContentLength());
1083}
1084
1085// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311086// connection, but the server gets impatient and closes the connection.
1087TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1088 SessionDependencies session_deps;
1089 scoped_ptr<HttpTransaction> trans(
1090 new HttpNetworkTransaction(CreateSession(&session_deps)));
1091
1092 HttpRequestInfo request;
1093 request.method = "GET";
1094 request.url = GURL("http://www.google.com/");
1095 request.load_flags = 0;
1096
1097 MockWrite data_writes1[] = {
1098 MockWrite("GET / HTTP/1.1\r\n"
1099 "Host: www.google.com\r\n"
1100 "Connection: keep-alive\r\n\r\n"),
1101 // This simulates the seemingly successful write to a closed connection
1102 // if the bug is not fixed.
1103 MockWrite("GET / HTTP/1.1\r\n"
1104 "Host: www.google.com\r\n"
1105 "Connection: keep-alive\r\n"
1106 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1107 };
1108
1109 MockRead data_reads1[] = {
1110 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1111 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1112 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1113 MockRead("Content-Length: 14\r\n\r\n"),
1114 // Tell MockTCPClientSocket to simulate the server closing the connection.
1115 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1116 MockRead("Unauthorized\r\n"),
1117 MockRead(false, OK), // The server closes the connection.
1118 };
1119
1120 // After calling trans->RestartWithAuth(), this is the request we should
1121 // be issuing -- the final header line contains the credentials.
1122 MockWrite data_writes2[] = {
1123 MockWrite("GET / HTTP/1.1\r\n"
1124 "Host: www.google.com\r\n"
1125 "Connection: keep-alive\r\n"
1126 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1127 };
1128
1129 // Lastly, the server responds with the actual content.
1130 MockRead data_reads2[] = {
1131 MockRead("HTTP/1.1 200 OK\r\n"),
1132 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1133 MockRead("Content-Length: 100\r\n\r\n"),
1134 MockRead(false, OK),
1135 };
1136
[email protected]31a2bfe2010-02-09 08:03:391137 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1138 data_writes1, arraysize(data_writes1));
1139 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1140 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311141 session_deps.socket_factory.AddSocketDataProvider(&data1);
1142 session_deps.socket_factory.AddSocketDataProvider(&data2);
1143
1144 TestCompletionCallback callback1;
1145
1146 int rv = trans->Start(&request, &callback1, NULL);
1147 EXPECT_EQ(ERR_IO_PENDING, rv);
1148
1149 rv = callback1.WaitForResult();
1150 EXPECT_EQ(OK, rv);
1151
1152 const HttpResponseInfo* response = trans->GetResponseInfo();
1153 EXPECT_FALSE(response == NULL);
1154
1155 // The password prompt info should have been set in response->auth_challenge.
1156 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1157
1158 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1159 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1160 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1161
1162 TestCompletionCallback callback2;
1163
1164 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1165 EXPECT_EQ(ERR_IO_PENDING, rv);
1166
1167 rv = callback2.WaitForResult();
1168 EXPECT_EQ(OK, rv);
1169
1170 response = trans->GetResponseInfo();
1171 ASSERT_FALSE(response == NULL);
1172 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1173 EXPECT_EQ(100, response->headers->GetContentLength());
1174}
1175
1176// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321177// proxy connection, when setting up an SSL tunnel.
1178TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1179 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591180 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1181 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321182
[email protected]5695b8c2009-09-30 21:36:431183 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321184
[email protected]1c773ea12009-04-28 19:58:421185 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321186 request.method = "GET";
1187 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461188 // Ensure that proxy authentication is attempted even
1189 // when the no authentication data flag is set.
1190 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321191
1192 // Since we have proxy, should try to establish tunnel.
1193 MockWrite data_writes1[] = {
1194 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451195 "Host: www.google.com\r\n"
1196 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321197
1198 // After calling trans->RestartWithAuth(), this is the request we should
1199 // be issuing -- the final header line contains the credentials.
1200 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1201 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451202 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321203 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1204 };
1205
1206 // The proxy responds to the connect with a 407, using a persistent
1207 // connection.
1208 MockRead data_reads1[] = {
1209 // No credentials.
1210 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1211 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1212 MockRead("Content-Length: 10\r\n\r\n"),
1213 MockRead("0123456789"),
1214
1215 // Wrong credentials (wrong password).
1216 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1217 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1218 MockRead("Content-Length: 10\r\n\r\n"),
1219 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421220 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321221 };
1222
[email protected]31a2bfe2010-02-09 08:03:391223 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1224 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591225 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321226
1227 TestCompletionCallback callback1;
1228
[email protected]684970b2009-08-14 04:54:461229 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421230 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321231
1232 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421233 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321234
[email protected]1c773ea12009-04-28 19:58:421235 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321236 EXPECT_FALSE(response == NULL);
1237
1238 EXPECT_TRUE(response->headers->IsKeepAlive());
1239 EXPECT_EQ(407, response->headers->response_code());
1240 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421241 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321242
1243 // The password prompt info should have been set in response->auth_challenge.
1244 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1245
[email protected]71e4573a2009-05-21 22:03:001246 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321247 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1248 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1249
1250 TestCompletionCallback callback2;
1251
1252 // Wrong password (should be "bar").
1253 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421254 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321255
1256 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421257 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321258
1259 response = trans->GetResponseInfo();
1260 EXPECT_FALSE(response == NULL);
1261
1262 EXPECT_TRUE(response->headers->IsKeepAlive());
1263 EXPECT_EQ(407, response->headers->response_code());
1264 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421265 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321266
1267 // The password prompt info should have been set in response->auth_challenge.
1268 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1269
[email protected]71e4573a2009-05-21 22:03:001270 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321271 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1272 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1273}
1274
[email protected]a8e9b162009-03-12 00:06:441275// Test that we don't read the response body when we fail to establish a tunnel,
1276// even if the user cancels the proxy's auth attempt.
1277TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1278 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591279 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441280
[email protected]e44de5d2009-06-05 20:12:451281 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441282
[email protected]5695b8c2009-09-30 21:36:431283 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441284
[email protected]1c773ea12009-04-28 19:58:421285 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441286 request.method = "GET";
1287 request.url = GURL("https://www.google.com/");
1288 request.load_flags = 0;
1289
1290 // Since we have proxy, should try to establish tunnel.
1291 MockWrite data_writes[] = {
1292 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451293 "Host: www.google.com\r\n"
1294 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441295 };
1296
1297 // The proxy responds to the connect with a 407.
1298 MockRead data_reads[] = {
1299 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1300 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1301 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421302 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441303 };
1304
[email protected]31a2bfe2010-02-09 08:03:391305 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1306 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591307 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441308
1309 TestCompletionCallback callback;
1310
[email protected]684970b2009-08-14 04:54:461311 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421312 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441313
1314 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421315 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441316
[email protected]1c773ea12009-04-28 19:58:421317 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441318 EXPECT_FALSE(response == NULL);
1319
1320 EXPECT_TRUE(response->headers->IsKeepAlive());
1321 EXPECT_EQ(407, response->headers->response_code());
1322 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421323 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441324
1325 std::string response_data;
1326 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421327 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441328}
1329
[email protected]ff007e162009-05-23 09:13:151330void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081331 const MockRead& status, int expected_status) {
1332 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591333 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081334
[email protected]228ff742009-06-05 01:19:591335 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081336
[email protected]5695b8c2009-09-30 21:36:431337 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081338
[email protected]1c773ea12009-04-28 19:58:421339 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081340 request.method = "GET";
1341 request.url = GURL("https://www.google.com/");
1342 request.load_flags = 0;
1343
1344 // Since we have proxy, should try to establish tunnel.
1345 MockWrite data_writes[] = {
1346 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451347 "Host: www.google.com\r\n"
1348 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081349 };
1350
1351 MockRead data_reads[] = {
1352 status,
1353 MockRead("Content-Length: 10\r\n\r\n"),
1354 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421355 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081356 };
1357
[email protected]31a2bfe2010-02-09 08:03:391358 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1359 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591360 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081361
1362 TestCompletionCallback callback;
1363
[email protected]684970b2009-08-14 04:54:461364 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421365 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081366
1367 rv = callback.WaitForResult();
1368 EXPECT_EQ(expected_status, rv);
1369}
1370
[email protected]ff007e162009-05-23 09:13:151371void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081372 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421373 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081374}
1375
1376TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1377 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1378}
1379
1380TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1381 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1382}
1383
1384TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1385 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1386}
1387
1388TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1389 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1390}
1391
1392TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1393 ConnectStatusHelper(
1394 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1395}
1396
1397TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1398 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1399}
1400
1401TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1402 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1403}
1404
1405TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1406 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1407}
1408
1409TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1410 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1411}
1412
1413TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1414 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1415}
1416
1417TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1418 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1419}
1420
1421TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1422 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1423}
1424
1425TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1426 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1427}
1428
1429TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1430 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1431}
1432
1433TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1434 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1435}
1436
1437TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1438 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1439}
1440
1441TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1442 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1443}
1444
1445TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1446 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1447}
1448
1449TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1450 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1451}
1452
1453TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1454 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1455}
1456
1457TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1458 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1459}
1460
1461TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1462 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1463}
1464
1465TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1466 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1467}
1468
1469TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1470 ConnectStatusHelperWithExpectedStatus(
1471 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421472 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081473}
1474
1475TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1476 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1477}
1478
1479TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1480 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1481}
1482
1483TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1484 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1485}
1486
1487TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1488 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1489}
1490
1491TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1492 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1493}
1494
1495TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1496 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1497}
1498
1499TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1500 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1501}
1502
1503TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1504 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1505}
1506
1507TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1508 ConnectStatusHelper(
1509 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1510}
1511
1512TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1513 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1514}
1515
1516TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1517 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1518}
1519
1520TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1521 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1522}
1523
1524TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1525 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1526}
1527
1528TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1529 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1530}
1531
1532TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1533 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1534}
1535
1536TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1537 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1538}
1539
[email protected]038e9a32008-10-08 22:40:161540// Test the flow when both the proxy server AND origin server require
1541// authentication. Again, this uses basic auth for both since that is
1542// the simplest to mock.
1543TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591544 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011545
[email protected]038e9a32008-10-08 22:40:161546 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421547 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431548 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161549
[email protected]1c773ea12009-04-28 19:58:421550 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161551 request.method = "GET";
1552 request.url = GURL("http://www.google.com/");
1553 request.load_flags = 0;
1554
[email protected]f9ee6b52008-11-08 06:46:231555 MockWrite data_writes1[] = {
1556 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1557 "Host: www.google.com\r\n"
1558 "Proxy-Connection: keep-alive\r\n\r\n"),
1559 };
1560
[email protected]038e9a32008-10-08 22:40:161561 MockRead data_reads1[] = {
1562 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1563 // Give a couple authenticate options (only the middle one is actually
1564 // supported).
[email protected]22927ad2009-09-21 19:56:191565 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161566 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1567 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1568 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1569 // Large content-length -- won't matter, as connection will be reset.
1570 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421571 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161572 };
1573
1574 // After calling trans->RestartWithAuth() the first time, this is the
1575 // request we should be issuing -- the final header line contains the
1576 // proxy's credentials.
1577 MockWrite data_writes2[] = {
1578 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1579 "Host: www.google.com\r\n"
1580 "Proxy-Connection: keep-alive\r\n"
1581 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1582 };
1583
1584 // Now the proxy server lets the request pass through to origin server.
1585 // The origin server responds with a 401.
1586 MockRead data_reads2[] = {
1587 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1588 // Note: We are using the same realm-name as the proxy server. This is
1589 // completely valid, as realms are unique across hosts.
1590 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1591 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1592 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421593 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161594 };
1595
1596 // After calling trans->RestartWithAuth() the second time, we should send
1597 // the credentials for both the proxy and origin server.
1598 MockWrite data_writes3[] = {
1599 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1600 "Host: www.google.com\r\n"
1601 "Proxy-Connection: keep-alive\r\n"
1602 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1603 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1604 };
1605
1606 // Lastly we get the desired content.
1607 MockRead data_reads3[] = {
1608 MockRead("HTTP/1.0 200 OK\r\n"),
1609 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1610 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421611 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161612 };
1613
[email protected]31a2bfe2010-02-09 08:03:391614 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1615 data_writes1, arraysize(data_writes1));
1616 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1617 data_writes2, arraysize(data_writes2));
1618 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1619 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591620 session_deps.socket_factory.AddSocketDataProvider(&data1);
1621 session_deps.socket_factory.AddSocketDataProvider(&data2);
1622 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161623
1624 TestCompletionCallback callback1;
1625
[email protected]684970b2009-08-14 04:54:461626 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421627 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161628
1629 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421630 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161631
[email protected]1c773ea12009-04-28 19:58:421632 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161633 EXPECT_FALSE(response == NULL);
1634
1635 // The password prompt info should have been set in response->auth_challenge.
1636 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1637
[email protected]71e4573a2009-05-21 22:03:001638 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161639 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1640 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1641
1642 TestCompletionCallback callback2;
1643
1644 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421645 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161646
1647 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421648 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161649
1650 response = trans->GetResponseInfo();
1651 EXPECT_FALSE(response == NULL);
1652 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1653
[email protected]71e4573a2009-05-21 22:03:001654 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161655 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1656 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1657
1658 TestCompletionCallback callback3;
1659
1660 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421661 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161662
1663 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421664 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161665
1666 response = trans->GetResponseInfo();
1667 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1668 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161669}
[email protected]4ddaf2502008-10-23 18:26:191670
[email protected]ea9dc9a2009-09-05 00:43:321671// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1672// can't hook into its internals to cause it to generate predictable NTLM
1673// authorization headers.
1674#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291675// The NTLM authentication unit tests were generated by capturing the HTTP
1676// requests and responses using Fiddler 2 and inspecting the generated random
1677// bytes in the debugger.
1678
1679// Enter the correct password and authenticate successfully.
1680TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421681 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201682 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591683 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401684 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431685 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241686
[email protected]1c773ea12009-04-28 19:58:421687 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241688 request.method = "GET";
1689 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1690 request.load_flags = 0;
1691
1692 MockWrite data_writes1[] = {
1693 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1694 "Host: 172.22.68.17\r\n"
1695 "Connection: keep-alive\r\n\r\n"),
1696 };
1697
1698 MockRead data_reads1[] = {
1699 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1700 // Negotiate and NTLM are often requested together. We only support NTLM.
1701 MockRead("WWW-Authenticate: Negotiate\r\n"),
1702 MockRead("WWW-Authenticate: NTLM\r\n"),
1703 MockRead("Connection: close\r\n"),
1704 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361705 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241706 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421707 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241708 };
1709
1710 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221711 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241712 // request we should be issuing -- the final header line contains a Type
1713 // 1 message.
1714 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1715 "Host: 172.22.68.17\r\n"
1716 "Connection: keep-alive\r\n"
1717 "Authorization: NTLM "
1718 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1719
1720 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1721 // (the credentials for the origin server). The second request continues
1722 // on the same connection.
1723 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1724 "Host: 172.22.68.17\r\n"
1725 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291726 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1727 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1728 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1729 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1730 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241731 };
1732
1733 MockRead data_reads2[] = {
1734 // The origin server responds with a Type 2 message.
1735 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1736 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291737 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241738 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1739 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1740 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1741 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1742 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1743 "BtAAAAAAA=\r\n"),
1744 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361745 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241746 MockRead("You are not authorized to view this page\r\n"),
1747
1748 // Lastly we get the desired content.
1749 MockRead("HTTP/1.1 200 OK\r\n"),
1750 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1751 MockRead("Content-Length: 13\r\n\r\n"),
1752 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421753 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241754 };
1755
[email protected]31a2bfe2010-02-09 08:03:391756 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1757 data_writes1, arraysize(data_writes1));
1758 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1759 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591760 session_deps.socket_factory.AddSocketDataProvider(&data1);
1761 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241762
1763 TestCompletionCallback callback1;
1764
[email protected]684970b2009-08-14 04:54:461765 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421766 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241767
1768 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421769 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241770
[email protected]0757e7702009-03-27 04:00:221771 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1772 TestCompletionCallback callback2;
1773 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421774 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221775 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421776 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221777 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1778
[email protected]1c773ea12009-04-28 19:58:421779 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241780 EXPECT_FALSE(response == NULL);
1781
1782 // The password prompt info should have been set in response->auth_challenge.
1783 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1784
[email protected]71e4573a2009-05-21 22:03:001785 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241786 EXPECT_EQ(L"", response->auth_challenge->realm);
1787 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1788
[email protected]0757e7702009-03-27 04:00:221789 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241790
[email protected]0757e7702009-03-27 04:00:221791 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421792 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241793
[email protected]0757e7702009-03-27 04:00:221794 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421795 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241796
1797 response = trans->GetResponseInfo();
1798 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1799 EXPECT_EQ(13, response->headers->GetContentLength());
1800}
1801
[email protected]385a4672009-03-11 22:21:291802// Enter a wrong password, and then the correct one.
1803TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421804 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201805 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591806 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401807 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431808 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291809
[email protected]1c773ea12009-04-28 19:58:421810 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291811 request.method = "GET";
1812 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1813 request.load_flags = 0;
1814
1815 MockWrite data_writes1[] = {
1816 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1817 "Host: 172.22.68.17\r\n"
1818 "Connection: keep-alive\r\n\r\n"),
1819 };
1820
1821 MockRead data_reads1[] = {
1822 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1823 // Negotiate and NTLM are often requested together. We only support NTLM.
1824 MockRead("WWW-Authenticate: Negotiate\r\n"),
1825 MockRead("WWW-Authenticate: NTLM\r\n"),
1826 MockRead("Connection: close\r\n"),
1827 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361828 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291829 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421830 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291831 };
1832
1833 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221834 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291835 // request we should be issuing -- the final header line contains a Type
1836 // 1 message.
1837 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1838 "Host: 172.22.68.17\r\n"
1839 "Connection: keep-alive\r\n"
1840 "Authorization: NTLM "
1841 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1842
1843 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1844 // (the credentials for the origin server). The second request continues
1845 // on the same connection.
1846 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1847 "Host: 172.22.68.17\r\n"
1848 "Connection: keep-alive\r\n"
1849 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1850 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1851 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1852 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1853 "4Ww7b7E=\r\n\r\n"),
1854 };
1855
1856 MockRead data_reads2[] = {
1857 // The origin server responds with a Type 2 message.
1858 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1859 MockRead("WWW-Authenticate: NTLM "
1860 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1861 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1862 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1863 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1864 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1865 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1866 "BtAAAAAAA=\r\n"),
1867 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361868 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291869 MockRead("You are not authorized to view this page\r\n"),
1870
1871 // Wrong password.
1872 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1873 MockRead("WWW-Authenticate: Negotiate\r\n"),
1874 MockRead("WWW-Authenticate: NTLM\r\n"),
1875 MockRead("Connection: close\r\n"),
1876 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361877 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291878 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421879 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291880 };
1881
1882 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221883 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291884 // request we should be issuing -- the final header line contains a Type
1885 // 1 message.
1886 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1887 "Host: 172.22.68.17\r\n"
1888 "Connection: keep-alive\r\n"
1889 "Authorization: NTLM "
1890 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1891
1892 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1893 // (the credentials for the origin server). The second request continues
1894 // on the same connection.
1895 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1896 "Host: 172.22.68.17\r\n"
1897 "Connection: keep-alive\r\n"
1898 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1899 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1900 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1901 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1902 "+4MUm7c=\r\n\r\n"),
1903 };
1904
1905 MockRead data_reads3[] = {
1906 // The origin server responds with a Type 2 message.
1907 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1908 MockRead("WWW-Authenticate: NTLM "
1909 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1910 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1911 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1912 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1913 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1914 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1915 "BtAAAAAAA=\r\n"),
1916 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361917 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291918 MockRead("You are not authorized to view this page\r\n"),
1919
1920 // Lastly we get the desired content.
1921 MockRead("HTTP/1.1 200 OK\r\n"),
1922 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1923 MockRead("Content-Length: 13\r\n\r\n"),
1924 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421925 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291926 };
1927
[email protected]31a2bfe2010-02-09 08:03:391928 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1929 data_writes1, arraysize(data_writes1));
1930 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1931 data_writes2, arraysize(data_writes2));
1932 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1933 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591934 session_deps.socket_factory.AddSocketDataProvider(&data1);
1935 session_deps.socket_factory.AddSocketDataProvider(&data2);
1936 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:291937
1938 TestCompletionCallback callback1;
1939
[email protected]684970b2009-08-14 04:54:461940 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421941 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291942
1943 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421944 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291945
[email protected]0757e7702009-03-27 04:00:221946 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291947 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221948 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421949 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291950 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421951 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221952 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291953
[email protected]1c773ea12009-04-28 19:58:421954 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291955 EXPECT_FALSE(response == NULL);
1956
1957 // The password prompt info should have been set in response->auth_challenge.
1958 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1959
[email protected]71e4573a2009-05-21 22:03:001960 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291961 EXPECT_EQ(L"", response->auth_challenge->realm);
1962 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1963
1964 TestCompletionCallback callback3;
1965
[email protected]0757e7702009-03-27 04:00:221966 // Enter the wrong password.
1967 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421968 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291969
1970 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421971 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291972
[email protected]0757e7702009-03-27 04:00:221973 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1974 TestCompletionCallback callback4;
1975 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421976 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221977 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421978 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221979 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1980
1981 response = trans->GetResponseInfo();
1982 EXPECT_FALSE(response == NULL);
1983
1984 // The password prompt info should have been set in response->auth_challenge.
1985 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1986
[email protected]71e4573a2009-05-21 22:03:001987 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221988 EXPECT_EQ(L"", response->auth_challenge->realm);
1989 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1990
1991 TestCompletionCallback callback5;
1992
1993 // Now enter the right password.
1994 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:421995 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221996
1997 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421998 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221999
[email protected]385a4672009-03-11 22:21:292000 response = trans->GetResponseInfo();
2001 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2002 EXPECT_EQ(13, response->headers->GetContentLength());
2003}
[email protected]ea9dc9a2009-09-05 00:43:322004#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292005
[email protected]4ddaf2502008-10-23 18:26:192006// Test reading a server response which has only headers, and no body.
2007// After some maximum number of bytes is consumed, the transaction should
2008// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2009TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592010 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402011 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432012 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192013
[email protected]1c773ea12009-04-28 19:58:422014 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192015 request.method = "GET";
2016 request.url = GURL("http://www.google.com/");
2017 request.load_flags = 0;
2018
[email protected]b75b7b2f2009-10-06 00:54:532019 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432020 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532021 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192022
2023 MockRead data_reads[] = {
2024 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432025 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192026 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422027 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192028 };
[email protected]31a2bfe2010-02-09 08:03:392029 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592030 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192031
2032 TestCompletionCallback callback;
2033
[email protected]684970b2009-08-14 04:54:462034 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422035 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192036
2037 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422038 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192039
[email protected]1c773ea12009-04-28 19:58:422040 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192041 EXPECT_TRUE(response == NULL);
2042}
[email protected]f4e426b2008-11-05 00:24:492043
2044// Make sure that we don't try to reuse a TCPClientSocket when failing to
2045// establish tunnel.
2046// http://code.google.com/p/chromium/issues/detail?id=3772
2047TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2048 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592049 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012050
[email protected]228ff742009-06-05 01:19:592051 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492052
[email protected]5695b8c2009-09-30 21:36:432053 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492054
[email protected]1c773ea12009-04-28 19:58:422055 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492056 request.method = "GET";
2057 request.url = GURL("https://www.google.com/");
2058 request.load_flags = 0;
2059
2060 // Since we have proxy, should try to establish tunnel.
2061 MockWrite data_writes1[] = {
2062 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452063 "Host: www.google.com\r\n"
2064 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492065 };
2066
[email protected]77848d12008-11-14 00:00:222067 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492068 // connection. Usually a proxy would return 501 (not implemented),
2069 // or 200 (tunnel established).
2070 MockRead data_reads1[] = {
2071 MockRead("HTTP/1.1 404 Not Found\r\n"),
2072 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422073 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492074 };
2075
[email protected]31a2bfe2010-02-09 08:03:392076 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2077 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592078 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492079
2080 TestCompletionCallback callback1;
2081
[email protected]684970b2009-08-14 04:54:462082 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422083 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492084
2085 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422086 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492087
[email protected]1c773ea12009-04-28 19:58:422088 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082089 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492090
[email protected]b4404c02009-04-10 16:38:522091 // Empty the current queue. This is necessary because idle sockets are
2092 // added to the connection pool asynchronously with a PostTask.
2093 MessageLoop::current()->RunAllPending();
2094
[email protected]f4e426b2008-11-05 00:24:492095 // We now check to make sure the TCPClientSocket was not added back to
2096 // the pool.
[email protected]a937a06d2009-08-19 21:19:242097 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492098 trans.reset();
[email protected]b4404c02009-04-10 16:38:522099 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492100 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242101 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492102}
[email protected]372d34a2008-11-05 21:30:512103
[email protected]1b157c02009-04-21 01:55:402104// Make sure that we recycle a socket after reading all of the response body.
2105TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592106 SessionDependencies session_deps;
2107 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402108
[email protected]5695b8c2009-09-30 21:36:432109 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402110
[email protected]1c773ea12009-04-28 19:58:422111 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402112 request.method = "GET";
2113 request.url = GURL("http://www.google.com/");
2114 request.load_flags = 0;
2115
2116 MockRead data_reads[] = {
2117 // A part of the response body is received with the response headers.
2118 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2119 // The rest of the response body is received in two parts.
2120 MockRead("lo"),
2121 MockRead(" world"),
2122 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422123 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402124 };
2125
[email protected]31a2bfe2010-02-09 08:03:392126 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592127 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402128
2129 TestCompletionCallback callback;
2130
[email protected]684970b2009-08-14 04:54:462131 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422132 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402133
2134 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422135 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402136
[email protected]1c773ea12009-04-28 19:58:422137 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402138 EXPECT_TRUE(response != NULL);
2139
2140 EXPECT_TRUE(response->headers != NULL);
2141 std::string status_line = response->headers->GetStatusLine();
2142 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2143
[email protected]a937a06d2009-08-19 21:19:242144 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402145
2146 std::string response_data;
2147 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422148 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402149 EXPECT_EQ("hello world", response_data);
2150
2151 // Empty the current queue. This is necessary because idle sockets are
2152 // added to the connection pool asynchronously with a PostTask.
2153 MessageLoop::current()->RunAllPending();
2154
2155 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242156 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402157}
2158
[email protected]b4404c02009-04-10 16:38:522159// Make sure that we recycle a socket after a zero-length response.
2160// http://crbug.com/9880
2161TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592162 SessionDependencies session_deps;
2163 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522164
[email protected]5695b8c2009-09-30 21:36:432165 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522166
[email protected]1c773ea12009-04-28 19:58:422167 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522168 request.method = "GET";
2169 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2170 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2171 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2172 "rt=prt.2642,ol.2649,xjs.2951");
2173 request.load_flags = 0;
2174
2175 MockRead data_reads[] = {
2176 MockRead("HTTP/1.1 204 No Content\r\n"
2177 "Content-Length: 0\r\n"
2178 "Content-Type: text/html\r\n\r\n"),
2179 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422180 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522181 };
2182
[email protected]31a2bfe2010-02-09 08:03:392183 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592184 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522185
2186 TestCompletionCallback callback;
2187
[email protected]684970b2009-08-14 04:54:462188 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422189 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522190
2191 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422192 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522193
[email protected]1c773ea12009-04-28 19:58:422194 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522195 EXPECT_TRUE(response != NULL);
2196
2197 EXPECT_TRUE(response->headers != NULL);
2198 std::string status_line = response->headers->GetStatusLine();
2199 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2200
[email protected]a937a06d2009-08-19 21:19:242201 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522202
2203 std::string response_data;
2204 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422205 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522206 EXPECT_EQ("", response_data);
2207
2208 // Empty the current queue. This is necessary because idle sockets are
2209 // added to the connection pool asynchronously with a PostTask.
2210 MessageLoop::current()->RunAllPending();
2211
2212 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242213 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522214}
2215
[email protected]372d34a2008-11-05 21:30:512216TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422217 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512218 // Transaction 1: a GET request that succeeds. The socket is recycled
2219 // after use.
2220 request[0].method = "GET";
2221 request[0].url = GURL("http://www.google.com/");
2222 request[0].load_flags = 0;
2223 // Transaction 2: a POST request. Reuses the socket kept alive from
2224 // transaction 1. The first attempts fails when writing the POST data.
2225 // This causes the transaction to retry with a new socket. The second
2226 // attempt succeeds.
2227 request[1].method = "POST";
2228 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422229 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512230 request[1].upload_data->AppendBytes("foo", 3);
2231 request[1].load_flags = 0;
2232
[email protected]228ff742009-06-05 01:19:592233 SessionDependencies session_deps;
2234 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512235
2236 // The first socket is used for transaction 1 and the first attempt of
2237 // transaction 2.
2238
2239 // The response of transaction 1.
2240 MockRead data_reads1[] = {
2241 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2242 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422243 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512244 };
2245 // The mock write results of transaction 1 and the first attempt of
2246 // transaction 2.
2247 MockWrite data_writes1[] = {
2248 MockWrite(false, 64), // GET
2249 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422250 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512251 };
[email protected]31a2bfe2010-02-09 08:03:392252 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2253 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512254
2255 // The second socket is used for the second attempt of transaction 2.
2256
2257 // The response of transaction 2.
2258 MockRead data_reads2[] = {
2259 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2260 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422261 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512262 };
2263 // The mock write results of the second attempt of transaction 2.
2264 MockWrite data_writes2[] = {
2265 MockWrite(false, 93), // POST
2266 MockWrite(false, 3), // POST data
2267 };
[email protected]31a2bfe2010-02-09 08:03:392268 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2269 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512270
[email protected]5ecc992a42009-11-11 01:41:592271 session_deps.socket_factory.AddSocketDataProvider(&data1);
2272 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512273
2274 const char* kExpectedResponseData[] = {
2275 "hello world", "welcome"
2276 };
2277
2278 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422279 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432280 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512281
2282 TestCompletionCallback callback;
2283
[email protected]684970b2009-08-14 04:54:462284 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422285 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512286
2287 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422288 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512289
[email protected]1c773ea12009-04-28 19:58:422290 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512291 EXPECT_TRUE(response != NULL);
2292
2293 EXPECT_TRUE(response->headers != NULL);
2294 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2295
2296 std::string response_data;
2297 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422298 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512299 EXPECT_EQ(kExpectedResponseData[i], response_data);
2300 }
2301}
[email protected]f9ee6b52008-11-08 06:46:232302
2303// Test the request-challenge-retry sequence for basic auth when there is
2304// an identity in the URL. The request should be sent as normal, but when
2305// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322306TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592307 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402308 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432309 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232310
[email protected]1c773ea12009-04-28 19:58:422311 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232312 request.method = "GET";
2313 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292314 request.url = GURL("http://foo:b@[email protected]/");
2315
2316 // The password contains an escaped character -- for this test to pass it
2317 // will need to be unescaped by HttpNetworkTransaction.
2318 EXPECT_EQ("b%40r", request.url.password());
2319
[email protected]ea9dc9a2009-09-05 00:43:322320 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232321
2322 MockWrite data_writes1[] = {
2323 MockWrite("GET / HTTP/1.1\r\n"
2324 "Host: www.google.com\r\n"
2325 "Connection: keep-alive\r\n\r\n"),
2326 };
2327
2328 MockRead data_reads1[] = {
2329 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2330 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2331 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422332 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232333 };
2334
2335 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322336 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232337 MockWrite data_writes2[] = {
2338 MockWrite("GET / HTTP/1.1\r\n"
2339 "Host: www.google.com\r\n"
2340 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292341 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232342 };
2343
2344 MockRead data_reads2[] = {
2345 MockRead("HTTP/1.0 200 OK\r\n"),
2346 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422347 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232348 };
2349
[email protected]31a2bfe2010-02-09 08:03:392350 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2351 data_writes1, arraysize(data_writes1));
2352 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2353 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592354 session_deps.socket_factory.AddSocketDataProvider(&data1);
2355 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232356
2357 TestCompletionCallback callback1;
2358
[email protected]684970b2009-08-14 04:54:462359 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422360 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232361
2362 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422363 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232364
[email protected]0757e7702009-03-27 04:00:222365 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2366 TestCompletionCallback callback2;
2367 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422368 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222369 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422370 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222371 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2372
[email protected]1c773ea12009-04-28 19:58:422373 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232374 EXPECT_FALSE(response == NULL);
2375
2376 // There is no challenge info, since the identity in URL worked.
2377 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2378
2379 EXPECT_EQ(100, response->headers->GetContentLength());
2380
2381 // Empty the current queue.
2382 MessageLoop::current()->RunAllPending();
2383}
2384
[email protected]ea9dc9a2009-09-05 00:43:322385// Test the request-challenge-retry sequence for basic auth when there is
2386// an incorrect identity in the URL. The identity from the URL should be used
2387// only once.
2388TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2389 SessionDependencies session_deps;
2390 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432391 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322392
2393 HttpRequestInfo request;
2394 request.method = "GET";
2395 // Note: the URL has a username:password in it. The password "baz" is
2396 // wrong (should be "bar").
2397 request.url = GURL("http://foo:[email protected]/");
2398
2399 request.load_flags = LOAD_NORMAL;
2400
2401 MockWrite data_writes1[] = {
2402 MockWrite("GET / HTTP/1.1\r\n"
2403 "Host: www.google.com\r\n"
2404 "Connection: keep-alive\r\n\r\n"),
2405 };
2406
2407 MockRead data_reads1[] = {
2408 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2409 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2410 MockRead("Content-Length: 10\r\n\r\n"),
2411 MockRead(false, ERR_FAILED),
2412 };
2413
2414 // After the challenge above, the transaction will be restarted using the
2415 // identity from the url (foo, baz) to answer the challenge.
2416 MockWrite data_writes2[] = {
2417 MockWrite("GET / HTTP/1.1\r\n"
2418 "Host: www.google.com\r\n"
2419 "Connection: keep-alive\r\n"
2420 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2421 };
2422
2423 MockRead data_reads2[] = {
2424 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2425 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2426 MockRead("Content-Length: 10\r\n\r\n"),
2427 MockRead(false, ERR_FAILED),
2428 };
2429
2430 // After the challenge above, the transaction will be restarted using the
2431 // identity supplied by the user (foo, bar) to answer the challenge.
2432 MockWrite data_writes3[] = {
2433 MockWrite("GET / HTTP/1.1\r\n"
2434 "Host: www.google.com\r\n"
2435 "Connection: keep-alive\r\n"
2436 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2437 };
2438
2439 MockRead data_reads3[] = {
2440 MockRead("HTTP/1.0 200 OK\r\n"),
2441 MockRead("Content-Length: 100\r\n\r\n"),
2442 MockRead(false, OK),
2443 };
2444
[email protected]31a2bfe2010-02-09 08:03:392445 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2446 data_writes1, arraysize(data_writes1));
2447 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2448 data_writes2, arraysize(data_writes2));
2449 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2450 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592451 session_deps.socket_factory.AddSocketDataProvider(&data1);
2452 session_deps.socket_factory.AddSocketDataProvider(&data2);
2453 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322454
2455 TestCompletionCallback callback1;
2456
2457 int rv = trans->Start(&request, &callback1, NULL);
2458 EXPECT_EQ(ERR_IO_PENDING, rv);
2459
2460 rv = callback1.WaitForResult();
2461 EXPECT_EQ(OK, rv);
2462
2463 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2464 TestCompletionCallback callback2;
2465 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2466 EXPECT_EQ(ERR_IO_PENDING, rv);
2467 rv = callback2.WaitForResult();
2468 EXPECT_EQ(OK, rv);
2469 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2470
2471 const HttpResponseInfo* response = trans->GetResponseInfo();
2472 EXPECT_FALSE(response == NULL);
2473 // The password prompt info should have been set in response->auth_challenge.
2474 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2475
2476 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2477 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2478 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2479
2480 TestCompletionCallback callback3;
2481 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2482 EXPECT_EQ(ERR_IO_PENDING, rv);
2483 rv = callback3.WaitForResult();
2484 EXPECT_EQ(OK, rv);
2485 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2486
2487 response = trans->GetResponseInfo();
2488 EXPECT_FALSE(response == NULL);
2489
2490 // There is no challenge info, since the identity worked.
2491 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2492
2493 EXPECT_EQ(100, response->headers->GetContentLength());
2494
2495 // Empty the current queue.
2496 MessageLoop::current()->RunAllPending();
2497}
2498
[email protected]f9ee6b52008-11-08 06:46:232499// Test that previously tried username/passwords for a realm get re-used.
2500TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592501 SessionDependencies session_deps;
2502 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232503
2504 // Transaction 1: authenticate (foo, bar) on MyRealm1
2505 {
[email protected]5695b8c2009-09-30 21:36:432506 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232507
[email protected]1c773ea12009-04-28 19:58:422508 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232509 request.method = "GET";
2510 request.url = GURL("http://www.google.com/x/y/z");
2511 request.load_flags = 0;
2512
2513 MockWrite data_writes1[] = {
2514 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2515 "Host: www.google.com\r\n"
2516 "Connection: keep-alive\r\n\r\n"),
2517 };
2518
2519 MockRead data_reads1[] = {
2520 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2521 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2522 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422523 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232524 };
2525
2526 // Resend with authorization (username=foo, password=bar)
2527 MockWrite data_writes2[] = {
2528 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2529 "Host: www.google.com\r\n"
2530 "Connection: keep-alive\r\n"
2531 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2532 };
2533
2534 // Sever accepts the authorization.
2535 MockRead data_reads2[] = {
2536 MockRead("HTTP/1.0 200 OK\r\n"),
2537 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422538 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232539 };
2540
[email protected]31a2bfe2010-02-09 08:03:392541 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2542 data_writes1, arraysize(data_writes1));
2543 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2544 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592545 session_deps.socket_factory.AddSocketDataProvider(&data1);
2546 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232547
2548 TestCompletionCallback callback1;
2549
[email protected]684970b2009-08-14 04:54:462550 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422551 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232552
2553 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422554 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232555
[email protected]1c773ea12009-04-28 19:58:422556 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232557 EXPECT_FALSE(response == NULL);
2558
2559 // The password prompt info should have been set in
2560 // response->auth_challenge.
2561 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2562
[email protected]71e4573a2009-05-21 22:03:002563 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232564 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2565 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2566
2567 TestCompletionCallback callback2;
2568
2569 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422570 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232571
2572 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422573 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232574
2575 response = trans->GetResponseInfo();
2576 EXPECT_FALSE(response == NULL);
2577 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2578 EXPECT_EQ(100, response->headers->GetContentLength());
2579 }
2580
2581 // ------------------------------------------------------------------------
2582
2583 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2584 {
[email protected]5695b8c2009-09-30 21:36:432585 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232586
[email protected]1c773ea12009-04-28 19:58:422587 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232588 request.method = "GET";
2589 // Note that Transaction 1 was at /x/y/z, so this is in the same
2590 // protection space as MyRealm1.
2591 request.url = GURL("http://www.google.com/x/y/a/b");
2592 request.load_flags = 0;
2593
2594 MockWrite data_writes1[] = {
2595 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2596 "Host: www.google.com\r\n"
2597 "Connection: keep-alive\r\n"
2598 // Send preemptive authorization for MyRealm1
2599 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2600 };
2601
2602 // The server didn't like the preemptive authorization, and
2603 // challenges us for a different realm (MyRealm2).
2604 MockRead data_reads1[] = {
2605 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2606 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2607 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422608 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232609 };
2610
2611 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2612 MockWrite data_writes2[] = {
2613 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2614 "Host: www.google.com\r\n"
2615 "Connection: keep-alive\r\n"
2616 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2617 };
2618
2619 // Sever accepts the authorization.
2620 MockRead data_reads2[] = {
2621 MockRead("HTTP/1.0 200 OK\r\n"),
2622 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422623 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232624 };
2625
[email protected]31a2bfe2010-02-09 08:03:392626 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2627 data_writes1, arraysize(data_writes1));
2628 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2629 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592630 session_deps.socket_factory.AddSocketDataProvider(&data1);
2631 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232632
2633 TestCompletionCallback callback1;
2634
[email protected]684970b2009-08-14 04:54:462635 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422636 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232637
2638 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422639 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232640
[email protected]1c773ea12009-04-28 19:58:422641 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232642 EXPECT_FALSE(response == NULL);
2643
2644 // The password prompt info should have been set in
2645 // response->auth_challenge.
2646 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2647
[email protected]71e4573a2009-05-21 22:03:002648 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232649 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2650 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2651
2652 TestCompletionCallback callback2;
2653
2654 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422655 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232656
2657 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422658 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232659
2660 response = trans->GetResponseInfo();
2661 EXPECT_FALSE(response == NULL);
2662 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2663 EXPECT_EQ(100, response->headers->GetContentLength());
2664 }
2665
2666 // ------------------------------------------------------------------------
2667
2668 // Transaction 3: Resend a request in MyRealm's protection space --
2669 // succeed with preemptive authorization.
2670 {
[email protected]5695b8c2009-09-30 21:36:432671 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232672
[email protected]1c773ea12009-04-28 19:58:422673 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232674 request.method = "GET";
2675 request.url = GURL("http://www.google.com/x/y/z2");
2676 request.load_flags = 0;
2677
2678 MockWrite data_writes1[] = {
2679 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2680 "Host: www.google.com\r\n"
2681 "Connection: keep-alive\r\n"
2682 // The authorization for MyRealm1 gets sent preemptively
2683 // (since the url is in the same protection space)
2684 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2685 };
2686
2687 // Sever accepts the preemptive authorization
2688 MockRead data_reads1[] = {
2689 MockRead("HTTP/1.0 200 OK\r\n"),
2690 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422691 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232692 };
2693
[email protected]31a2bfe2010-02-09 08:03:392694 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2695 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592696 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232697
2698 TestCompletionCallback callback1;
2699
[email protected]684970b2009-08-14 04:54:462700 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422701 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232702
2703 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422704 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232705
[email protected]1c773ea12009-04-28 19:58:422706 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232707 EXPECT_FALSE(response == NULL);
2708
2709 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2710 EXPECT_EQ(100, response->headers->GetContentLength());
2711 }
2712
2713 // ------------------------------------------------------------------------
2714
2715 // Transaction 4: request another URL in MyRealm (however the
2716 // url is not known to belong to the protection space, so no pre-auth).
2717 {
[email protected]5695b8c2009-09-30 21:36:432718 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232719
[email protected]1c773ea12009-04-28 19:58:422720 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232721 request.method = "GET";
2722 request.url = GURL("http://www.google.com/x/1");
2723 request.load_flags = 0;
2724
2725 MockWrite data_writes1[] = {
2726 MockWrite("GET /x/1 HTTP/1.1\r\n"
2727 "Host: www.google.com\r\n"
2728 "Connection: keep-alive\r\n\r\n"),
2729 };
2730
2731 MockRead data_reads1[] = {
2732 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2733 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2734 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422735 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232736 };
2737
2738 // Resend with authorization from MyRealm's cache.
2739 MockWrite data_writes2[] = {
2740 MockWrite("GET /x/1 HTTP/1.1\r\n"
2741 "Host: www.google.com\r\n"
2742 "Connection: keep-alive\r\n"
2743 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2744 };
2745
2746 // Sever accepts the authorization.
2747 MockRead data_reads2[] = {
2748 MockRead("HTTP/1.0 200 OK\r\n"),
2749 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422750 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232751 };
2752
[email protected]31a2bfe2010-02-09 08:03:392753 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2754 data_writes1, arraysize(data_writes1));
2755 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2756 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592757 session_deps.socket_factory.AddSocketDataProvider(&data1);
2758 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232759
2760 TestCompletionCallback callback1;
2761
[email protected]684970b2009-08-14 04:54:462762 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422763 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232764
2765 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422766 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232767
[email protected]0757e7702009-03-27 04:00:222768 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2769 TestCompletionCallback callback2;
2770 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422771 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222772 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422773 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222774 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2775
[email protected]1c773ea12009-04-28 19:58:422776 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232777 EXPECT_FALSE(response == NULL);
2778 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2779 EXPECT_EQ(100, response->headers->GetContentLength());
2780 }
2781
2782 // ------------------------------------------------------------------------
2783
2784 // Transaction 5: request a URL in MyRealm, but the server rejects the
2785 // cached identity. Should invalidate and re-prompt.
2786 {
[email protected]5695b8c2009-09-30 21:36:432787 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232788
[email protected]1c773ea12009-04-28 19:58:422789 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232790 request.method = "GET";
2791 request.url = GURL("http://www.google.com/p/q/t");
2792 request.load_flags = 0;
2793
2794 MockWrite data_writes1[] = {
2795 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2796 "Host: www.google.com\r\n"
2797 "Connection: keep-alive\r\n\r\n"),
2798 };
2799
2800 MockRead data_reads1[] = {
2801 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2802 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2803 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422804 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232805 };
2806
2807 // Resend with authorization from cache for MyRealm.
2808 MockWrite data_writes2[] = {
2809 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2810 "Host: www.google.com\r\n"
2811 "Connection: keep-alive\r\n"
2812 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2813 };
2814
2815 // Sever rejects the authorization.
2816 MockRead data_reads2[] = {
2817 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2818 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2819 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422820 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232821 };
2822
2823 // At this point we should prompt for new credentials for MyRealm.
2824 // Restart with username=foo3, password=foo4.
2825 MockWrite data_writes3[] = {
2826 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2827 "Host: www.google.com\r\n"
2828 "Connection: keep-alive\r\n"
2829 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2830 };
2831
2832 // Sever accepts the authorization.
2833 MockRead data_reads3[] = {
2834 MockRead("HTTP/1.0 200 OK\r\n"),
2835 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422836 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232837 };
2838
[email protected]31a2bfe2010-02-09 08:03:392839 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2840 data_writes1, arraysize(data_writes1));
2841 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2842 data_writes2, arraysize(data_writes2));
2843 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2844 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592845 session_deps.socket_factory.AddSocketDataProvider(&data1);
2846 session_deps.socket_factory.AddSocketDataProvider(&data2);
2847 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232848
2849 TestCompletionCallback callback1;
2850
[email protected]684970b2009-08-14 04:54:462851 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422852 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232853
2854 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422855 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232856
[email protected]0757e7702009-03-27 04:00:222857 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2858 TestCompletionCallback callback2;
2859 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422860 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222861 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422862 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222863 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2864
[email protected]1c773ea12009-04-28 19:58:422865 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232866 EXPECT_FALSE(response == NULL);
2867
2868 // The password prompt info should have been set in
2869 // response->auth_challenge.
2870 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2871
[email protected]71e4573a2009-05-21 22:03:002872 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232873 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2874 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2875
[email protected]0757e7702009-03-27 04:00:222876 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232877
[email protected]0757e7702009-03-27 04:00:222878 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422879 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232880
[email protected]0757e7702009-03-27 04:00:222881 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422882 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232883
2884 response = trans->GetResponseInfo();
2885 EXPECT_FALSE(response == NULL);
2886 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2887 EXPECT_EQ(100, response->headers->GetContentLength());
2888 }
2889}
[email protected]89ceba9a2009-03-21 03:46:062890
2891// Test the ResetStateForRestart() private method.
2892TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2893 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592894 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402895 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432896 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062897
2898 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062899 trans->read_buf_ = new IOBuffer(15);
2900 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572901 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062902
2903 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:142904 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:572905 response->auth_challenge = new AuthChallengeInfo();
2906 response->ssl_info.cert_status = -15;
2907 response->response_time = base::Time::Now();
2908 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062909
2910 { // Setup state for response_.vary_data
2911 HttpRequestInfo request;
2912 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2913 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:572914 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]89ceba9a2009-03-21 03:46:062915 request.extra_headers = "Foo: 1\nbar: 23";
[email protected]0877e3d2009-10-17 22:29:572916 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:062917 }
2918
2919 // Cause the above state to be reset.
2920 trans->ResetStateForRestart();
2921
2922 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:072923 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:062924 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:572925 EXPECT_EQ(0U, trans->request_headers_.size());
2926 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2927 EXPECT_TRUE(response->headers.get() == NULL);
2928 EXPECT_EQ(false, response->was_cached);
2929 EXPECT_EQ(0, response->ssl_info.cert_status);
2930 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:062931}
2932
[email protected]bacff652009-03-31 17:50:332933// Test HTTPS connections to a site with a bad certificate
2934TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592935 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402936 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432937 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332938
2939 HttpRequestInfo request;
2940 request.method = "GET";
2941 request.url = GURL("https://www.google.com/");
2942 request.load_flags = 0;
2943
2944 MockWrite data_writes[] = {
2945 MockWrite("GET / HTTP/1.1\r\n"
2946 "Host: www.google.com\r\n"
2947 "Connection: keep-alive\r\n\r\n"),
2948 };
2949
2950 MockRead data_reads[] = {
2951 MockRead("HTTP/1.0 200 OK\r\n"),
2952 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2953 MockRead("Content-Length: 100\r\n\r\n"),
2954 MockRead(false, OK),
2955 };
2956
[email protected]5ecc992a42009-11-11 01:41:592957 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:392958 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2959 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592960 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2961 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:332962
[email protected]5ecc992a42009-11-11 01:41:592963 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2964 session_deps.socket_factory.AddSocketDataProvider(&data);
2965 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2966 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:332967
2968 TestCompletionCallback callback;
2969
[email protected]684970b2009-08-14 04:54:462970 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332971 EXPECT_EQ(ERR_IO_PENDING, rv);
2972
2973 rv = callback.WaitForResult();
2974 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2975
2976 rv = trans->RestartIgnoringLastError(&callback);
2977 EXPECT_EQ(ERR_IO_PENDING, rv);
2978
2979 rv = callback.WaitForResult();
2980 EXPECT_EQ(OK, rv);
2981
2982 const HttpResponseInfo* response = trans->GetResponseInfo();
2983
2984 EXPECT_FALSE(response == NULL);
2985 EXPECT_EQ(100, response->headers->GetContentLength());
2986}
2987
2988// Test HTTPS connections to a site with a bad certificate, going through a
2989// proxy
2990TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592991 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332992
2993 HttpRequestInfo request;
2994 request.method = "GET";
2995 request.url = GURL("https://www.google.com/");
2996 request.load_flags = 0;
2997
2998 MockWrite proxy_writes[] = {
2999 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453000 "Host: www.google.com\r\n"
3001 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333002 };
3003
3004 MockRead proxy_reads[] = {
3005 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423006 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333007 };
3008
3009 MockWrite data_writes[] = {
3010 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453011 "Host: www.google.com\r\n"
3012 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333013 MockWrite("GET / HTTP/1.1\r\n"
3014 "Host: www.google.com\r\n"
3015 "Connection: keep-alive\r\n\r\n"),
3016 };
3017
3018 MockRead data_reads[] = {
3019 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3020 MockRead("HTTP/1.0 200 OK\r\n"),
3021 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3022 MockRead("Content-Length: 100\r\n\r\n"),
3023 MockRead(false, OK),
3024 };
3025
[email protected]31a2bfe2010-02-09 08:03:393026 StaticSocketDataProvider ssl_bad_certificate(
3027 proxy_reads, arraysize(proxy_reads),
3028 proxy_writes, arraysize(proxy_writes));
3029 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3030 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593031 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3032 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333033
[email protected]5ecc992a42009-11-11 01:41:593034 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3035 session_deps.socket_factory.AddSocketDataProvider(&data);
3036 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3037 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333038
3039 TestCompletionCallback callback;
3040
3041 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593042 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333043
[email protected]d207a5f2009-06-04 05:28:403044 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433045 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333046
[email protected]684970b2009-08-14 04:54:463047 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:333048 EXPECT_EQ(ERR_IO_PENDING, rv);
3049
3050 rv = callback.WaitForResult();
3051 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3052
3053 rv = trans->RestartIgnoringLastError(&callback);
3054 EXPECT_EQ(ERR_IO_PENDING, rv);
3055
3056 rv = callback.WaitForResult();
3057 EXPECT_EQ(OK, rv);
3058
3059 const HttpResponseInfo* response = trans->GetResponseInfo();
3060
3061 EXPECT_FALSE(response == NULL);
3062 EXPECT_EQ(100, response->headers->GetContentLength());
3063 }
3064}
3065
[email protected]1c773ea12009-04-28 19:58:423066TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593067 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403068 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433069 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423070
3071 HttpRequestInfo request;
3072 request.method = "GET";
3073 request.url = GURL("http://www.google.com/");
3074 request.user_agent = "Chromium Ultra Awesome X Edition";
3075
3076 MockWrite data_writes[] = {
3077 MockWrite("GET / HTTP/1.1\r\n"
3078 "Host: www.google.com\r\n"
3079 "Connection: keep-alive\r\n"
3080 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3081 };
3082
3083 // Lastly, the server responds with the actual content.
3084 MockRead data_reads[] = {
3085 MockRead("HTTP/1.0 200 OK\r\n"),
3086 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3087 MockRead("Content-Length: 100\r\n\r\n"),
3088 MockRead(false, OK),
3089 };
3090
[email protected]31a2bfe2010-02-09 08:03:393091 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3092 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593093 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423094
3095 TestCompletionCallback callback;
3096
[email protected]684970b2009-08-14 04:54:463097 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423098 EXPECT_EQ(ERR_IO_PENDING, rv);
3099
3100 rv = callback.WaitForResult();
3101 EXPECT_EQ(OK, rv);
3102}
3103
3104TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593105 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403106 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433107 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423108
3109 HttpRequestInfo request;
3110 request.method = "GET";
3111 request.url = GURL("http://www.google.com/");
3112 request.load_flags = 0;
3113 request.referrer = GURL("http://the.previous.site.com/");
3114
3115 MockWrite data_writes[] = {
3116 MockWrite("GET / HTTP/1.1\r\n"
3117 "Host: www.google.com\r\n"
3118 "Connection: keep-alive\r\n"
3119 "Referer: http://the.previous.site.com/\r\n\r\n"),
3120 };
3121
3122 // Lastly, the server responds with the actual content.
3123 MockRead data_reads[] = {
3124 MockRead("HTTP/1.0 200 OK\r\n"),
3125 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3126 MockRead("Content-Length: 100\r\n\r\n"),
3127 MockRead(false, OK),
3128 };
3129
[email protected]31a2bfe2010-02-09 08:03:393130 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3131 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593132 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423133
3134 TestCompletionCallback callback;
3135
[email protected]684970b2009-08-14 04:54:463136 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423137 EXPECT_EQ(ERR_IO_PENDING, rv);
3138
3139 rv = callback.WaitForResult();
3140 EXPECT_EQ(OK, rv);
3141}
3142
3143TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593144 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403145 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433146 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423147
3148 HttpRequestInfo request;
3149 request.method = "POST";
3150 request.url = GURL("http://www.google.com/");
3151
3152 MockWrite data_writes[] = {
3153 MockWrite("POST / HTTP/1.1\r\n"
3154 "Host: www.google.com\r\n"
3155 "Connection: keep-alive\r\n"
3156 "Content-Length: 0\r\n\r\n"),
3157 };
3158
3159 // Lastly, the server responds with the actual content.
3160 MockRead data_reads[] = {
3161 MockRead("HTTP/1.0 200 OK\r\n"),
3162 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3163 MockRead("Content-Length: 100\r\n\r\n"),
3164 MockRead(false, OK),
3165 };
3166
[email protected]31a2bfe2010-02-09 08:03:393167 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3168 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593169 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423170
3171 TestCompletionCallback callback;
3172
[email protected]684970b2009-08-14 04:54:463173 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423174 EXPECT_EQ(ERR_IO_PENDING, rv);
3175
3176 rv = callback.WaitForResult();
3177 EXPECT_EQ(OK, rv);
3178}
3179
3180TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593181 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403182 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433183 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423184
3185 HttpRequestInfo request;
3186 request.method = "PUT";
3187 request.url = GURL("http://www.google.com/");
3188
3189 MockWrite data_writes[] = {
3190 MockWrite("PUT / HTTP/1.1\r\n"
3191 "Host: www.google.com\r\n"
3192 "Connection: keep-alive\r\n"
3193 "Content-Length: 0\r\n\r\n"),
3194 };
3195
3196 // Lastly, the server responds with the actual content.
3197 MockRead data_reads[] = {
3198 MockRead("HTTP/1.0 200 OK\r\n"),
3199 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3200 MockRead("Content-Length: 100\r\n\r\n"),
3201 MockRead(false, OK),
3202 };
3203
[email protected]31a2bfe2010-02-09 08:03:393204 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3205 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593206 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423207
3208 TestCompletionCallback callback;
3209
[email protected]684970b2009-08-14 04:54:463210 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423211 EXPECT_EQ(ERR_IO_PENDING, rv);
3212
3213 rv = callback.WaitForResult();
3214 EXPECT_EQ(OK, rv);
3215}
3216
3217TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593218 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403219 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433220 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423221
3222 HttpRequestInfo request;
3223 request.method = "HEAD";
3224 request.url = GURL("http://www.google.com/");
3225
3226 MockWrite data_writes[] = {
3227 MockWrite("HEAD / HTTP/1.1\r\n"
3228 "Host: www.google.com\r\n"
3229 "Connection: keep-alive\r\n"
3230 "Content-Length: 0\r\n\r\n"),
3231 };
3232
3233 // Lastly, the server responds with the actual content.
3234 MockRead data_reads[] = {
3235 MockRead("HTTP/1.0 200 OK\r\n"),
3236 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3237 MockRead("Content-Length: 100\r\n\r\n"),
3238 MockRead(false, OK),
3239 };
3240
[email protected]31a2bfe2010-02-09 08:03:393241 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3242 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593243 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423244
3245 TestCompletionCallback callback;
3246
[email protected]684970b2009-08-14 04:54:463247 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423248 EXPECT_EQ(ERR_IO_PENDING, rv);
3249
3250 rv = callback.WaitForResult();
3251 EXPECT_EQ(OK, rv);
3252}
3253
3254TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593255 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403256 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433257 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423258
3259 HttpRequestInfo request;
3260 request.method = "GET";
3261 request.url = GURL("http://www.google.com/");
3262 request.load_flags = LOAD_BYPASS_CACHE;
3263
3264 MockWrite data_writes[] = {
3265 MockWrite("GET / HTTP/1.1\r\n"
3266 "Host: www.google.com\r\n"
3267 "Connection: keep-alive\r\n"
3268 "Pragma: no-cache\r\n"
3269 "Cache-Control: no-cache\r\n\r\n"),
3270 };
3271
3272 // Lastly, the server responds with the actual content.
3273 MockRead data_reads[] = {
3274 MockRead("HTTP/1.0 200 OK\r\n"),
3275 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3276 MockRead("Content-Length: 100\r\n\r\n"),
3277 MockRead(false, OK),
3278 };
3279
[email protected]31a2bfe2010-02-09 08:03:393280 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3281 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593282 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423283
3284 TestCompletionCallback callback;
3285
[email protected]684970b2009-08-14 04:54:463286 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423287 EXPECT_EQ(ERR_IO_PENDING, rv);
3288
3289 rv = callback.WaitForResult();
3290 EXPECT_EQ(OK, rv);
3291}
3292
3293TEST_F(HttpNetworkTransactionTest,
3294 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593295 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403296 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433297 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423298
3299 HttpRequestInfo request;
3300 request.method = "GET";
3301 request.url = GURL("http://www.google.com/");
3302 request.load_flags = LOAD_VALIDATE_CACHE;
3303
3304 MockWrite data_writes[] = {
3305 MockWrite("GET / HTTP/1.1\r\n"
3306 "Host: www.google.com\r\n"
3307 "Connection: keep-alive\r\n"
3308 "Cache-Control: max-age=0\r\n\r\n"),
3309 };
3310
3311 // Lastly, the server responds with the actual content.
3312 MockRead data_reads[] = {
3313 MockRead("HTTP/1.0 200 OK\r\n"),
3314 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3315 MockRead("Content-Length: 100\r\n\r\n"),
3316 MockRead(false, OK),
3317 };
3318
[email protected]31a2bfe2010-02-09 08:03:393319 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3320 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593321 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423322
3323 TestCompletionCallback callback;
3324
[email protected]684970b2009-08-14 04:54:463325 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423326 EXPECT_EQ(ERR_IO_PENDING, rv);
3327
3328 rv = callback.WaitForResult();
3329 EXPECT_EQ(OK, rv);
3330}
3331
3332TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593333 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403334 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433335 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423336
3337 HttpRequestInfo request;
3338 request.method = "GET";
3339 request.url = GURL("http://www.google.com/");
3340 request.extra_headers = "FooHeader: Bar\r\n";
3341
3342 MockWrite data_writes[] = {
3343 MockWrite("GET / HTTP/1.1\r\n"
3344 "Host: www.google.com\r\n"
3345 "Connection: keep-alive\r\n"
3346 "FooHeader: Bar\r\n\r\n"),
3347 };
3348
3349 // Lastly, the server responds with the actual content.
3350 MockRead data_reads[] = {
3351 MockRead("HTTP/1.0 200 OK\r\n"),
3352 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3353 MockRead("Content-Length: 100\r\n\r\n"),
3354 MockRead(false, OK),
3355 };
3356
[email protected]31a2bfe2010-02-09 08:03:393357 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3358 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593359 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423360
3361 TestCompletionCallback callback;
3362
[email protected]684970b2009-08-14 04:54:463363 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423364 EXPECT_EQ(ERR_IO_PENDING, rv);
3365
3366 rv = callback.WaitForResult();
3367 EXPECT_EQ(OK, rv);
3368}
3369
[email protected]3cd17242009-06-23 02:59:023370TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093371 SessionDependencies session_deps(
3372 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023373
3374 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433375 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023376
3377 HttpRequestInfo request;
3378 request.method = "GET";
3379 request.url = GURL("http://www.google.com/");
3380 request.load_flags = 0;
3381
3382 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3383 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3384
3385 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353386 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023387 MockWrite("GET / HTTP/1.1\r\n"
3388 "Host: www.google.com\r\n"
3389 "Connection: keep-alive\r\n\r\n")
3390 };
3391
3392 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593393 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023394 MockRead("HTTP/1.0 200 OK\r\n"),
3395 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3396 MockRead("Payload"),
3397 MockRead(false, OK)
3398 };
3399
[email protected]31a2bfe2010-02-09 08:03:393400 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3401 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593402 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023403
3404 TestCompletionCallback callback;
3405
[email protected]684970b2009-08-14 04:54:463406 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023407 EXPECT_EQ(ERR_IO_PENDING, rv);
3408
3409 rv = callback.WaitForResult();
3410 EXPECT_EQ(OK, rv);
3411
3412 const HttpResponseInfo* response = trans->GetResponseInfo();
3413 EXPECT_FALSE(response == NULL);
3414
3415 std::string response_text;
3416 rv = ReadTransaction(trans.get(), &response_text);
3417 EXPECT_EQ(OK, rv);
3418 EXPECT_EQ("Payload", response_text);
3419}
3420
3421TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093422 SessionDependencies session_deps(
3423 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023424
3425 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433426 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023427
3428 HttpRequestInfo request;
3429 request.method = "GET";
3430 request.url = GURL("https://www.google.com/");
3431 request.load_flags = 0;
3432
3433 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3434 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3435
3436 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353437 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3438 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023439 MockWrite("GET / HTTP/1.1\r\n"
3440 "Host: www.google.com\r\n"
3441 "Connection: keep-alive\r\n\r\n")
3442 };
3443
3444 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353445 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3446 arraysize(read_buffer)),
3447 MockRead("HTTP/1.0 200 OK\r\n"),
3448 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3449 MockRead("Payload"),
3450 MockRead(false, OK)
3451 };
3452
[email protected]31a2bfe2010-02-09 08:03:393453 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3454 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593455 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353456
[email protected]5ecc992a42009-11-11 01:41:593457 SSLSocketDataProvider ssl(true, OK);
3458 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353459
3460 TestCompletionCallback callback;
3461
[email protected]684970b2009-08-14 04:54:463462 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353463 EXPECT_EQ(ERR_IO_PENDING, rv);
3464
3465 rv = callback.WaitForResult();
3466 EXPECT_EQ(OK, rv);
3467
3468 const HttpResponseInfo* response = trans->GetResponseInfo();
3469 EXPECT_FALSE(response == NULL);
3470
3471 std::string response_text;
3472 rv = ReadTransaction(trans.get(), &response_text);
3473 EXPECT_EQ(OK, rv);
3474 EXPECT_EQ("Payload", response_text);
3475}
3476
3477TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093478 SessionDependencies session_deps(
3479 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353480
3481 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433482 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353483
3484 HttpRequestInfo request;
3485 request.method = "GET";
3486 request.url = GURL("http://www.google.com/");
3487 request.load_flags = 0;
3488
3489 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3490 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373491 const char kSOCKS5OkRequest[] = {
3492 0x05, // Version
3493 0x01, // Command (CONNECT)
3494 0x00, // Reserved.
3495 0x03, // Address type (DOMAINNAME).
3496 0x0E, // Length of domain (14)
3497 // Domain string:
3498 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3499 0x00, 0x50, // 16-bit port (80)
3500 };
[email protected]e0c27be2009-07-15 13:09:353501 const char kSOCKS5OkResponse[] =
3502 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3503
3504 MockWrite data_writes[] = {
3505 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3506 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3507 MockWrite("GET / HTTP/1.1\r\n"
3508 "Host: www.google.com\r\n"
3509 "Connection: keep-alive\r\n\r\n")
3510 };
3511
3512 MockRead data_reads[] = {
3513 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3514 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3515 MockRead("HTTP/1.0 200 OK\r\n"),
3516 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3517 MockRead("Payload"),
3518 MockRead(false, OK)
3519 };
3520
[email protected]31a2bfe2010-02-09 08:03:393521 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3522 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593523 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353524
3525 TestCompletionCallback callback;
3526
[email protected]684970b2009-08-14 04:54:463527 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353528 EXPECT_EQ(ERR_IO_PENDING, rv);
3529
3530 rv = callback.WaitForResult();
3531 EXPECT_EQ(OK, rv);
3532
3533 const HttpResponseInfo* response = trans->GetResponseInfo();
3534 EXPECT_FALSE(response == NULL);
3535
3536 std::string response_text;
3537 rv = ReadTransaction(trans.get(), &response_text);
3538 EXPECT_EQ(OK, rv);
3539 EXPECT_EQ("Payload", response_text);
3540}
3541
3542TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093543 SessionDependencies session_deps(
3544 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353545
3546 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433547 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353548
3549 HttpRequestInfo request;
3550 request.method = "GET";
3551 request.url = GURL("https://www.google.com/");
3552 request.load_flags = 0;
3553
3554 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3555 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373556 const unsigned char kSOCKS5OkRequest[] = {
3557 0x05, // Version
3558 0x01, // Command (CONNECT)
3559 0x00, // Reserved.
3560 0x03, // Address type (DOMAINNAME).
3561 0x0E, // Length of domain (14)
3562 // Domain string:
3563 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3564 0x01, 0xBB, // 16-bit port (443)
3565 };
3566
[email protected]e0c27be2009-07-15 13:09:353567 const char kSOCKS5OkResponse[] =
3568 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3569
3570 MockWrite data_writes[] = {
3571 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3572 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3573 arraysize(kSOCKS5OkRequest)),
3574 MockWrite("GET / HTTP/1.1\r\n"
3575 "Host: www.google.com\r\n"
3576 "Connection: keep-alive\r\n\r\n")
3577 };
3578
3579 MockRead data_reads[] = {
3580 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3581 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023582 MockRead("HTTP/1.0 200 OK\r\n"),
3583 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3584 MockRead("Payload"),
3585 MockRead(false, OK)
3586 };
3587
[email protected]31a2bfe2010-02-09 08:03:393588 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3589 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593590 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023591
[email protected]5ecc992a42009-11-11 01:41:593592 SSLSocketDataProvider ssl(true, OK);
3593 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023594
3595 TestCompletionCallback callback;
3596
[email protected]684970b2009-08-14 04:54:463597 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023598 EXPECT_EQ(ERR_IO_PENDING, rv);
3599
3600 rv = callback.WaitForResult();
3601 EXPECT_EQ(OK, rv);
3602
3603 const HttpResponseInfo* response = trans->GetResponseInfo();
3604 EXPECT_FALSE(response == NULL);
3605
3606 std::string response_text;
3607 rv = ReadTransaction(trans.get(), &response_text);
3608 EXPECT_EQ(OK, rv);
3609 EXPECT_EQ("Payload", response_text);
3610}
3611
[email protected]04e5be32009-06-26 20:00:313612// Tests that for connection endpoints the group names are correctly set.
3613TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3614 const struct {
3615 const std::string proxy_server;
3616 const std::string url;
3617 const std::string expected_group_name;
3618 } tests[] = {
3619 {
3620 "", // no proxy (direct)
3621 "http://www.google.com/direct",
3622 "http://www.google.com/",
3623 },
3624 {
3625 "http_proxy",
3626 "http://www.google.com/http_proxy_normal",
3627 "proxy/http_proxy:80/",
3628 },
3629 {
3630 "socks4://socks_proxy:1080",
3631 "http://www.google.com/socks4_direct",
3632 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3633 },
3634
3635 // SSL Tests
3636 {
3637 "",
3638 "https://www.google.com/direct_ssl",
3639 "https://www.google.com/",
3640 },
3641 {
3642 "http_proxy",
3643 "https://www.google.com/http_connect_ssl",
3644 "proxy/http_proxy:80/https://www.google.com/",
3645 },
3646 {
3647 "socks4://socks_proxy:1080",
3648 "https://www.google.com/socks4_ssl",
3649 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3650 },
3651 };
3652
3653 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093654 SessionDependencies session_deps(
3655 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313656
3657 scoped_refptr<CaptureGroupNameSocketPool> conn_pool(
3658 new CaptureGroupNameSocketPool());
3659
3660 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a937a06d2009-08-19 21:19:243661 session->tcp_socket_pool_ = conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313662
[email protected]5695b8c2009-09-30 21:36:433663 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313664
3665 HttpRequestInfo request;
3666 request.method = "GET";
3667 request.url = GURL(tests[i].url);
3668 request.load_flags = 0;
3669
3670 TestCompletionCallback callback;
3671
3672 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463673 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]04e5be32009-06-26 20:00:313674 EXPECT_EQ(tests[i].expected_group_name,
3675 conn_pool->last_group_name_received());
3676 }
3677}
3678
[email protected]9172a982009-06-06 00:30:253679TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543680 SessionDependencies session_deps(
3681 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323682
[email protected]69719062010-01-05 20:09:213683 // This simulates failure resolving all hostnames; that means we will fail
3684 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:323685 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3686
[email protected]9172a982009-06-06 00:30:253687 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433688 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253689
3690 HttpRequestInfo request;
3691 request.method = "GET";
3692 request.url = GURL("http://www.google.com/");
3693
3694 TestCompletionCallback callback;
3695
[email protected]684970b2009-08-14 04:54:463696 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253697 EXPECT_EQ(ERR_IO_PENDING, rv);
3698
[email protected]9172a982009-06-06 00:30:253699 rv = callback.WaitForResult();
3700 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3701}
3702
[email protected]f3e6c1e2009-06-15 20:52:123703// Host resolution observer used by
3704// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3705// resovle requests are issued with a referrer of |expected_referrer|.
3706class ResolutionReferrerObserver : public HostResolver::Observer {
3707 public:
3708 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3709 : expected_referrer_(expected_referrer),
3710 called_start_with_referrer_(false),
3711 called_finish_with_referrer_(false) {
3712 }
3713
3714 virtual void OnStartResolution(int id,
3715 const HostResolver::RequestInfo& info) {
3716 if (info.referrer() == expected_referrer_)
3717 called_start_with_referrer_ = true;
3718 }
3719
3720 virtual void OnFinishResolutionWithStatus(
3721 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3722 if (info.referrer() == expected_referrer_)
3723 called_finish_with_referrer_ = true;
3724 }
3725
[email protected]eb255d32009-06-17 02:11:033726 virtual void OnCancelResolution(int id,
3727 const HostResolver::RequestInfo& info ) {
3728 FAIL() << "Should not be cancelling any requests!";
3729 }
3730
[email protected]f3e6c1e2009-06-15 20:52:123731 bool did_complete_with_expected_referrer() const {
3732 return called_start_with_referrer_ && called_finish_with_referrer_;
3733 }
3734
3735 private:
3736 GURL expected_referrer_;
3737 bool called_start_with_referrer_;
3738 bool called_finish_with_referrer_;
3739
3740 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3741};
3742
3743// Make sure that when HostResolver::Resolve() is invoked, it passes through
3744// the "referrer". This is depended on by the DNS prefetch observer.
3745TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3746 GURL referrer = GURL("http://expected-referrer/");
3747 EXPECT_TRUE(referrer.is_valid());
3748 ResolutionReferrerObserver resolution_observer(referrer);
3749
3750 SessionDependencies session_deps;
3751 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433752 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123753
3754 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143755 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123756
3757 // Connect up a mock socket which will fail when reading.
3758 MockRead data_reads[] = {
3759 MockRead(false, ERR_FAILED),
3760 };
[email protected]31a2bfe2010-02-09 08:03:393761 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593762 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:123763
3764 // Issue a request, containing an HTTP referrer.
3765 HttpRequestInfo request;
3766 request.method = "GET";
3767 request.referrer = referrer;
3768 request.url = GURL("http://www.google.com/");
3769
3770 // Run the request until it fails reading from the socket.
3771 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463772 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123773 EXPECT_EQ(ERR_IO_PENDING, rv);
3774 rv = callback.WaitForResult();
3775 EXPECT_EQ(ERR_FAILED, rv);
3776
3777 // Check that the host resolution observer saw |referrer|.
3778 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3779}
3780
[email protected]3b9cca42009-06-16 01:08:283781// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3782// host cache is bypassed.
3783TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3784 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323785
[email protected]a2c2fb92009-07-18 07:31:043786 // Select a host resolver that does caching.
3787 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323788
[email protected]3b9cca42009-06-16 01:08:283789 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433790 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:283791
3792 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3793 // a synchronous lookup.)
3794 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143795 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463796 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3797 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283798 EXPECT_EQ(OK, rv);
3799
3800 // Verify that it was added to host cache, by doing a subsequent async lookup
3801 // and confirming it completes synchronously.
3802 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463803 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283804 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463805 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323806 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283807
3808 // Inject a failure the next time that "www.google.com" is resolved. This way
3809 // we can tell if the next lookup hit the cache, or the "network".
3810 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323811 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283812
3813 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3814 // first read -- this won't be reached as the host resolution will fail first.
3815 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:393816 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593817 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:283818
3819 // Issue a request, asking to bypass the cache(s).
3820 HttpRequestInfo request;
3821 request.method = "GET";
3822 request.load_flags = LOAD_BYPASS_CACHE;
3823 request.url = GURL("http://www.google.com/");
3824
3825 // Run the request.
3826 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463827 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283828 ASSERT_EQ(ERR_IO_PENDING, rv);
3829 rv = callback.WaitForResult();
3830
3831 // If we bypassed the cache, we would have gotten a failure while resolving
3832 // "www.google.com".
3833 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3834}
3835
[email protected]0877e3d2009-10-17 22:29:573836// Make sure we can handle an error when writing the request.
3837TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3838 SessionDependencies session_deps;
3839 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3840
3841 HttpRequestInfo request;
3842 request.method = "GET";
3843 request.url = GURL("http://www.foo.com/");
3844 request.load_flags = 0;
3845
3846 MockWrite write_failure[] = {
3847 MockWrite(true, ERR_CONNECTION_RESET),
3848 };
[email protected]31a2bfe2010-02-09 08:03:393849 StaticSocketDataProvider data(NULL, 0,
3850 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:593851 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573852
3853 TestCompletionCallback callback;
3854
3855 scoped_ptr<HttpTransaction> trans(
3856 new HttpNetworkTransaction(CreateSession(&session_deps)));
3857
3858 int rv = trans->Start(&request, &callback, NULL);
3859 EXPECT_EQ(ERR_IO_PENDING, rv);
3860
3861 rv = callback.WaitForResult();
3862 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3863}
3864
3865// Check that a connection closed after the start of the headers finishes ok.
3866TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3867 SessionDependencies session_deps;
3868 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3869
3870 HttpRequestInfo request;
3871 request.method = "GET";
3872 request.url = GURL("http://www.foo.com/");
3873 request.load_flags = 0;
3874
3875 MockRead data_reads[] = {
3876 MockRead("HTTP/1."),
3877 MockRead(false, OK),
3878 };
3879
[email protected]31a2bfe2010-02-09 08:03:393880 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593881 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573882
3883 TestCompletionCallback callback;
3884
3885 scoped_ptr<HttpTransaction> trans(
3886 new HttpNetworkTransaction(CreateSession(&session_deps)));
3887
3888 int rv = trans->Start(&request, &callback, NULL);
3889 EXPECT_EQ(ERR_IO_PENDING, rv);
3890
3891 rv = callback.WaitForResult();
3892 EXPECT_EQ(OK, rv);
3893
3894 const HttpResponseInfo* response = trans->GetResponseInfo();
3895 EXPECT_TRUE(response != NULL);
3896
3897 EXPECT_TRUE(response->headers != NULL);
3898 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
3899
3900 std::string response_data;
3901 rv = ReadTransaction(trans.get(), &response_data);
3902 EXPECT_EQ(OK, rv);
3903 EXPECT_EQ("", response_data);
3904}
3905
3906// Make sure that a dropped connection while draining the body for auth
3907// restart does the right thing.
3908TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
3909 SessionDependencies session_deps;
3910 scoped_ptr<HttpTransaction> trans(
3911 new HttpNetworkTransaction(CreateSession(&session_deps)));
3912
3913 HttpRequestInfo request;
3914 request.method = "GET";
3915 request.url = GURL("http://www.google.com/");
3916 request.load_flags = 0;
3917
3918 MockWrite data_writes1[] = {
3919 MockWrite("GET / HTTP/1.1\r\n"
3920 "Host: www.google.com\r\n"
3921 "Connection: keep-alive\r\n\r\n"),
3922 };
3923
3924 MockRead data_reads1[] = {
3925 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3926 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3927 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3928 MockRead("Content-Length: 14\r\n\r\n"),
3929 MockRead("Unauth"),
3930 MockRead(true, ERR_CONNECTION_RESET),
3931 };
3932
[email protected]31a2bfe2010-02-09 08:03:393933 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3934 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593935 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:573936
3937 // After calling trans->RestartWithAuth(), this is the request we should
3938 // be issuing -- the final header line contains the credentials.
3939 MockWrite data_writes2[] = {
3940 MockWrite("GET / HTTP/1.1\r\n"
3941 "Host: www.google.com\r\n"
3942 "Connection: keep-alive\r\n"
3943 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3944 };
3945
3946 // Lastly, the server responds with the actual content.
3947 MockRead data_reads2[] = {
3948 MockRead("HTTP/1.1 200 OK\r\n"),
3949 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3950 MockRead("Content-Length: 100\r\n\r\n"),
3951 MockRead(false, OK),
3952 };
3953
[email protected]31a2bfe2010-02-09 08:03:393954 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3955 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593956 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:573957
3958 TestCompletionCallback callback1;
3959
3960 int rv = trans->Start(&request, &callback1, NULL);
3961 EXPECT_EQ(ERR_IO_PENDING, rv);
3962
3963 rv = callback1.WaitForResult();
3964 EXPECT_EQ(OK, rv);
3965
3966 const HttpResponseInfo* response = trans->GetResponseInfo();
3967 EXPECT_FALSE(response == NULL);
3968
3969 // The password prompt info should have been set in response->auth_challenge.
3970 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3971
3972 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3973 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3974 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3975
3976 TestCompletionCallback callback2;
3977
3978 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3979 EXPECT_EQ(ERR_IO_PENDING, rv);
3980
3981 rv = callback2.WaitForResult();
3982 EXPECT_EQ(OK, rv);
3983
3984 response = trans->GetResponseInfo();
3985 EXPECT_FALSE(response == NULL);
3986 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3987 EXPECT_EQ(100, response->headers->GetContentLength());
3988}
3989
3990// Test HTTPS connections going through a proxy that sends extra data.
3991TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
3992 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
3993
3994 HttpRequestInfo request;
3995 request.method = "GET";
3996 request.url = GURL("https://www.google.com/");
3997 request.load_flags = 0;
3998
3999 MockRead proxy_reads[] = {
4000 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4001 MockRead(false, OK)
4002 };
4003
[email protected]31a2bfe2010-02-09 08:03:394004 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594005 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574006
[email protected]5ecc992a42009-11-11 01:41:594007 session_deps.socket_factory.AddSocketDataProvider(&data);
4008 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574009
4010 TestCompletionCallback callback;
4011
4012 session_deps.socket_factory.ResetNextMockIndexes();
4013
4014 scoped_ptr<HttpTransaction> trans(
4015 new HttpNetworkTransaction(CreateSession(&session_deps)));
4016
4017 int rv = trans->Start(&request, &callback, NULL);
4018 EXPECT_EQ(ERR_IO_PENDING, rv);
4019
4020 rv = callback.WaitForResult();
4021 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4022}
4023
[email protected]e22e1362009-11-23 21:31:124024TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464025 SessionDependencies session_deps;
4026 scoped_ptr<HttpTransaction> trans(
4027 new HttpNetworkTransaction(CreateSession(&session_deps)));
4028
4029 HttpRequestInfo request;
4030 request.method = "GET";
4031 request.url = GURL("http://www.google.com/");
4032 request.load_flags = 0;
4033
[email protected]e22e1362009-11-23 21:31:124034 MockRead data_reads[] = {
4035 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4036 MockRead(false, OK),
4037 };
[email protected]9492e4a2010-02-24 00:58:464038
4039 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4040 session_deps.socket_factory.AddSocketDataProvider(&data);
4041
4042 TestCompletionCallback callback;
4043
4044 int rv = trans->Start(&request, &callback, NULL);
4045 EXPECT_EQ(ERR_IO_PENDING, rv);
4046
4047 EXPECT_EQ(OK, callback.WaitForResult());
4048
4049 const HttpResponseInfo* response = trans->GetResponseInfo();
4050 EXPECT_TRUE(response != NULL);
4051
4052 EXPECT_TRUE(response->headers != NULL);
4053 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4054
4055 std::string response_data;
4056 rv = ReadTransaction(trans.get(), &response_data);
4057 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124058}
4059
[email protected]95d88ffe2010-02-04 21:25:334060TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4061 SessionDependencies session_deps;
4062 scoped_ptr<HttpTransaction> trans(
4063 new HttpNetworkTransaction(CreateSession(&session_deps)));
4064
4065 HttpRequestInfo request;
4066 request.method = "POST";
4067 request.url = GURL("http://www.google.com/upload");
4068 request.upload_data = new UploadData;
4069 request.load_flags = 0;
4070
4071 FilePath temp_file_path;
4072 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4073 const uint64 kFakeSize = 100000; // file is actually blank
4074
4075 std::vector<UploadData::Element> elements;
4076 UploadData::Element element;
4077 element.SetToFilePath(temp_file_path);
4078 element.SetContentLength(kFakeSize);
4079 elements.push_back(element);
4080 request.upload_data->set_elements(elements);
4081 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4082
4083 MockRead data_reads[] = {
4084 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4085 MockRead("hello world"),
4086 MockRead(false, OK),
4087 };
[email protected]31a2bfe2010-02-09 08:03:394088 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334089 session_deps.socket_factory.AddSocketDataProvider(&data);
4090
4091 TestCompletionCallback callback;
4092
4093 int rv = trans->Start(&request, &callback, NULL);
4094 EXPECT_EQ(ERR_IO_PENDING, rv);
4095
4096 rv = callback.WaitForResult();
4097 EXPECT_EQ(OK, rv);
4098
4099 const HttpResponseInfo* response = trans->GetResponseInfo();
4100 EXPECT_TRUE(response != NULL);
4101
4102 EXPECT_TRUE(response->headers != NULL);
4103 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4104
4105 std::string response_data;
4106 rv = ReadTransaction(trans.get(), &response_data);
4107 EXPECT_EQ(OK, rv);
4108 EXPECT_EQ("hello world", response_data);
4109
4110 file_util::Delete(temp_file_path, false);
4111}
4112
[email protected]aeefc9e82010-02-19 16:18:274113// Tests that changes to Auth realms are treated like auth rejections.
4114TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4115 SessionDependencies session_deps;
4116 scoped_ptr<HttpTransaction> trans(
4117 new HttpNetworkTransaction(CreateSession(&session_deps)));
4118
4119 HttpRequestInfo request;
4120 request.method = "GET";
4121 request.url = GURL("http://www.google.com/");
4122 request.load_flags = 0;
4123
4124 // First transaction will request a resource and receive a Basic challenge
4125 // with realm="first_realm".
4126 MockWrite data_writes1[] = {
4127 MockWrite("GET / HTTP/1.1\r\n"
4128 "Host: www.google.com\r\n"
4129 "Connection: keep-alive\r\n"
4130 "\r\n"),
4131 };
4132 MockRead data_reads1[] = {
4133 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4134 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4135 "\r\n"),
4136 };
4137
4138 // After calling trans->RestartWithAuth(), provide an Authentication header
4139 // for first_realm. The server will reject and provide a challenge with
4140 // second_realm.
4141 MockWrite data_writes2[] = {
4142 MockWrite("GET / HTTP/1.1\r\n"
4143 "Host: www.google.com\r\n"
4144 "Connection: keep-alive\r\n"
4145 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4146 "\r\n"),
4147 };
4148 MockRead data_reads2[] = {
4149 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4150 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4151 "\r\n"),
4152 };
4153
4154 // This again fails, and goes back to first_realm. Make sure that the
4155 // entry is removed from cache.
4156 MockWrite data_writes3[] = {
4157 MockWrite("GET / HTTP/1.1\r\n"
4158 "Host: www.google.com\r\n"
4159 "Connection: keep-alive\r\n"
4160 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4161 "\r\n"),
4162 };
4163 MockRead data_reads3[] = {
4164 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4165 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4166 "\r\n"),
4167 };
4168
4169 // Try one last time (with the correct password) and get the resource.
4170 MockWrite data_writes4[] = {
4171 MockWrite("GET / HTTP/1.1\r\n"
4172 "Host: www.google.com\r\n"
4173 "Connection: keep-alive\r\n"
4174 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4175 "\r\n"),
4176 };
4177 MockRead data_reads4[] = {
4178 MockRead("HTTP/1.1 200 OK\r\n"
4179 "Content-Type: text/html; charset=iso-8859-1\r\n"
4180 "Content-Length: 100\r\n"
4181 "\r\n"),
4182 };
4183
4184 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4185 data_writes1, arraysize(data_writes1));
4186 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4187 data_writes2, arraysize(data_writes2));
4188 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4189 data_writes3, arraysize(data_writes3));
4190 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4191 data_writes4, arraysize(data_writes4));
4192 session_deps.socket_factory.AddSocketDataProvider(&data1);
4193 session_deps.socket_factory.AddSocketDataProvider(&data2);
4194 session_deps.socket_factory.AddSocketDataProvider(&data3);
4195 session_deps.socket_factory.AddSocketDataProvider(&data4);
4196
4197 TestCompletionCallback callback1;
4198
4199 // Issue the first request with Authorize headers. There should be a
4200 // password prompt for first_realm waiting to be filled in after the
4201 // transaction completes.
4202 int rv = trans->Start(&request, &callback1, NULL);
4203 EXPECT_EQ(ERR_IO_PENDING, rv);
4204 rv = callback1.WaitForResult();
4205 EXPECT_EQ(OK, rv);
4206 const HttpResponseInfo* response = trans->GetResponseInfo();
4207 ASSERT_FALSE(response == NULL);
4208 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4209 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4210 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4211 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4212
4213 // Issue the second request with an incorrect password. There should be a
4214 // password prompt for second_realm waiting to be filled in after the
4215 // transaction completes.
4216 TestCompletionCallback callback2;
4217 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4218 EXPECT_EQ(ERR_IO_PENDING, rv);
4219 rv = callback2.WaitForResult();
4220 EXPECT_EQ(OK, rv);
4221 response = trans->GetResponseInfo();
4222 ASSERT_FALSE(response == NULL);
4223 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4224 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4225 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4226 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4227
4228 // Issue the third request with another incorrect password. There should be
4229 // a password prompt for first_realm waiting to be filled in. If the password
4230 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4231 // first_realm was not correctly removed.
4232 TestCompletionCallback callback3;
4233 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4234 EXPECT_EQ(ERR_IO_PENDING, rv);
4235 rv = callback3.WaitForResult();
4236 EXPECT_EQ(OK, rv);
4237 response = trans->GetResponseInfo();
4238 ASSERT_FALSE(response == NULL);
4239 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4240 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4241 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4242 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4243
4244 // Issue the fourth request with the correct password and username.
4245 TestCompletionCallback callback4;
4246 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4247 EXPECT_EQ(ERR_IO_PENDING, rv);
4248 rv = callback4.WaitForResult();
4249 EXPECT_EQ(OK, rv);
4250 response = trans->GetResponseInfo();
4251 ASSERT_FALSE(response == NULL);
4252 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4253}
4254
[email protected]564b4912010-03-09 16:30:424255TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
4256 SessionDependencies session_deps;
4257
4258 MockRead data_reads[] = {
4259 MockRead("HTTP/1.1 200 OK\r\n"),
4260 MockRead("Alternate-Protocol: 443:SPDY\r\n\r\n"),
4261 MockRead("hello world"),
4262 MockRead(false, OK),
4263 };
4264
4265 HttpRequestInfo request;
4266 request.method = "GET";
4267 request.url = GURL("http://www.google.com/");
4268 request.load_flags = 0;
4269
4270 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4271
4272 session_deps.socket_factory.AddSocketDataProvider(&data);
4273
4274 TestCompletionCallback callback;
4275
4276 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4277 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4278
4279 int rv = trans->Start(&request, &callback, NULL);
4280 EXPECT_EQ(ERR_IO_PENDING, rv);
4281
4282 HostPortPair http_host_port_pair;
4283 http_host_port_pair.host = "www.google.com";
4284 http_host_port_pair.port = 80;
4285 const HttpAlternateProtocols& alternate_protocols =
4286 session->alternate_protocols();
4287 EXPECT_FALSE(
4288 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4289
4290 EXPECT_EQ(OK, callback.WaitForResult());
4291
4292 const HttpResponseInfo* response = trans->GetResponseInfo();
4293 ASSERT_TRUE(response != NULL);
4294 ASSERT_TRUE(response->headers != NULL);
4295 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4296
4297 std::string response_data;
4298 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4299 EXPECT_EQ("hello world", response_data);
4300
4301 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4302 const HttpAlternateProtocols::PortProtocolPair alternate =
4303 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4304 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4305 expected_alternate.port = 443;
4306 expected_alternate.protocol = HttpAlternateProtocols::SPDY;
4307 EXPECT_TRUE(expected_alternate.Equals(alternate));
4308}
4309
4310TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
4311 SessionDependencies session_deps;
4312
4313 HttpRequestInfo request;
4314 request.method = "GET";
4315 request.url = GURL("http://www.google.com/");
4316 request.load_flags = 0;
4317
4318 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4319 StaticSocketDataProvider first_data;
4320 first_data.set_connect_data(mock_connect);
4321 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4322
4323 MockRead data_reads[] = {
4324 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4325 MockRead("hello world"),
4326 MockRead(true, OK),
4327 };
4328 StaticSocketDataProvider second_data(
4329 data_reads, arraysize(data_reads), NULL, 0);
4330 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4331
4332 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4333 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4334 // http://crbug.com/37454.
4335 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4336
4337 TestCompletionCallback callback;
4338
4339 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4340
4341 HostPortPair http_host_port_pair;
4342 http_host_port_pair.host = "www.google.com";
4343 http_host_port_pair.port = 80;
4344 HttpAlternateProtocols* alternate_protocols =
4345 session->mutable_alternate_protocols();
4346 alternate_protocols->SetAlternateProtocolFor(
4347 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
4348 HttpAlternateProtocols::SPDY);
4349
4350 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4351
4352 int rv = trans->Start(&request, &callback, NULL);
4353 EXPECT_EQ(ERR_IO_PENDING, rv);
4354 EXPECT_EQ(OK, callback.WaitForResult());
4355
4356 const HttpResponseInfo* response = trans->GetResponseInfo();
4357 ASSERT_TRUE(response != NULL);
4358 ASSERT_TRUE(response->headers != NULL);
4359 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4360
4361 std::string response_data;
4362 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4363 EXPECT_EQ("hello world", response_data);
4364
4365 ASSERT_TRUE(
4366 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
4367 const HttpAlternateProtocols::PortProtocolPair alternate =
4368 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
4369 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
4370}
4371
4372// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
4373// says that it does SPDY, but it just does the TLS handshake, but the NPN
4374// response does not indicate SPDY, so we just do standard HTTPS over the port.
4375// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
4376// on the original port.
4377TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
4378 SessionDependencies session_deps;
4379
4380 HttpRequestInfo request;
4381 request.method = "GET";
4382 request.url = GURL("http://www.google.com/");
4383 request.load_flags = 0;
4384
4385 MockRead data_reads[] = {
4386 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4387 MockRead("hello world"),
4388 MockRead(true, OK),
4389 };
4390 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4391 session_deps.socket_factory.AddSocketDataProvider(&data);
4392
4393 SSLSocketDataProvider ssl(true, OK);
4394 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4395
4396 TestCompletionCallback callback;
4397
4398 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4399
4400 HostPortPair http_host_port_pair;
4401 http_host_port_pair.host = "www.google.com";
4402 http_host_port_pair.port = 80;
4403 HttpAlternateProtocols* alternate_protocols =
4404 session->mutable_alternate_protocols();
4405 alternate_protocols->SetAlternateProtocolFor(
4406 http_host_port_pair, 1234 /* port is ignored */,
4407 HttpAlternateProtocols::SPDY);
4408
4409 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4410
4411 int rv = trans->Start(&request, &callback, NULL);
4412 EXPECT_EQ(ERR_IO_PENDING, rv);
4413 EXPECT_EQ(OK, callback.WaitForResult());
4414
4415 const HttpResponseInfo* response = trans->GetResponseInfo();
4416 ASSERT_TRUE(response != NULL);
4417 ASSERT_TRUE(response->headers != NULL);
4418 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4419
4420 std::string response_data;
4421 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4422 EXPECT_EQ("hello world", response_data);
4423}
4424
[email protected]89ceba9a2009-03-21 03:46:064425} // namespace net