blob: 8c0d8bd89f609092569b8788d5dbae783d6060cf [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]6624b4622010-03-29 19:58:3611#include "base/scoped_ptr.h"
[email protected]bacff652009-03-31 17:50:3312#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3213#include "net/base/mock_host_resolver.h"
[email protected]ac790b42009-12-02 04:31:3114#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4215#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3316#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5217#include "net/base/test_completion_callback.h"
18#include "net/base/upload_data.h"
[email protected]dab9c7d2010-02-06 21:44:3219#include "net/spdy/spdy_session_pool.h"
[email protected]385a4672009-03-11 22:21:2920#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5721#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5222#include "net/http/http_network_session.h"
23#include "net/http/http_network_transaction.h"
[email protected]0877e3d2009-10-17 22:29:5724#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5225#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5326#include "net/proxy/proxy_config_service_fixed.h"
[email protected]f7984fc62009-06-22 23:26:4427#include "net/socket/client_socket_factory.h"
28#include "net/socket/socket_test_util.h"
29#include "net/socket/ssl_client_socket.h"
initial.commit586acc5fe2008-07-26 22:42:5230#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1531#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5232
33//-----------------------------------------------------------------------------
34
[email protected]89ceba9a2009-03-21 03:46:0635namespace net {
36
[email protected]e44de5d2009-06-05 20:12:4537// Helper to manage the lifetimes of the dependencies for a
38// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5939class SessionDependencies {
40 public:
41 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4242 SessionDependencies()
43 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:3744 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:1045 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]61a86c42010-04-19 22:45:5346 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
47 spdy_session_pool(new SpdySessionPool) {}
[email protected]228ff742009-06-05 01:19:5948
49 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4550 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4251 : host_resolver(new MockHostResolver),
52 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1053 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]61a86c42010-04-19 22:45:5354 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
55 spdy_session_pool(new SpdySessionPool) {}
[email protected]228ff742009-06-05 01:19:5956
[email protected]a2c2fb92009-07-18 07:31:0457 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0958 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4259 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5960 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:5061 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]61a86c42010-04-19 22:45:5362 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]228ff742009-06-05 01:19:5963};
64
[email protected]1c773ea12009-04-28 19:58:4265ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5066 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:4867 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3968 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5369}
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]61a86c42010-04-19 22:45:5377 session_deps->spdy_session_pool,
[email protected]fa55e192010-02-15 14:25:5078 session_deps->http_auth_handler_factory.get());
[email protected]e8d536192008-10-17 22:21:1479}
80
[email protected]89836e22008-09-25 20:33:4281class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:5282 public:
[email protected]0e75a732008-10-16 20:36:0983 virtual void TearDown() {
84 // Empty the current queue.
85 MessageLoop::current()->RunAllPending();
86 PlatformTest::TearDown();
87 }
88
[email protected]3d2a59b2008-09-26 19:44:2589 protected:
90 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:5291
[email protected]ff007e162009-05-23 09:13:1592 struct SimpleGetHelperResult {
93 int rv;
94 std::string status_line;
95 std::string response_data;
96 };
initial.commit586acc5fe2008-07-26 22:42:5297
[email protected]31a2bfe2010-02-09 08:03:3998 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
99 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15100 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52101
[email protected]228ff742009-06-05 01:19:59102 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40103 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43104 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52105
[email protected]ff007e162009-05-23 09:13:15106 HttpRequestInfo request;
107 request.method = "GET";
108 request.url = GURL("http://www.google.com/");
109 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52110
[email protected]31a2bfe2010-02-09 08:03:39111 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59112 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52113
[email protected]ff007e162009-05-23 09:13:15114 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52115
[email protected]684970b2009-08-14 04:54:46116 int rv = trans->Start(&request, &callback, NULL);
[email protected]ff007e162009-05-23 09:13:15117 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52118
[email protected]ff007e162009-05-23 09:13:15119 out.rv = callback.WaitForResult();
120 if (out.rv != OK)
121 return out;
122
123 const HttpResponseInfo* response = trans->GetResponseInfo();
124 EXPECT_TRUE(response != NULL);
125
126 EXPECT_TRUE(response->headers != NULL);
127 out.status_line = response->headers->GetStatusLine();
128
129 rv = ReadTransaction(trans.get(), &out.response_data);
130 EXPECT_EQ(OK, rv);
131
[email protected]aecfbf22008-10-16 02:02:47132 return out;
[email protected]ff007e162009-05-23 09:13:15133 }
initial.commit586acc5fe2008-07-26 22:42:52134
[email protected]ff007e162009-05-23 09:13:15135 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
136 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52137
[email protected]ff007e162009-05-23 09:13:15138 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15139};
[email protected]231d5a32008-09-13 00:45:27140
[email protected]15a5ccf82008-10-23 19:57:43141// Fill |str| with a long header list that consumes >= |size| bytes.
142void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19143 const char* row =
144 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
145 const int sizeof_row = strlen(row);
146 const int num_rows = static_cast<int>(
147 ceil(static_cast<float>(size) / sizeof_row));
148 const int sizeof_data = num_rows * sizeof_row;
149 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43150 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51151
[email protected]4ddaf2502008-10-23 18:26:19152 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43153 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19154}
155
[email protected]385a4672009-03-11 22:21:29156// Alternative functions that eliminate randomness and dependency on the local
157// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20158void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29159 static const uint8 bytes[] = {
160 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
161 };
162 static size_t current_byte = 0;
163 for (size_t i = 0; i < n; ++i) {
164 output[i] = bytes[current_byte++];
165 current_byte %= arraysize(bytes);
166 }
167}
168
[email protected]fe2bc6a2009-03-23 16:52:20169void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29170 static const uint8 bytes[] = {
171 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
172 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
173 };
174 static size_t current_byte = 0;
175 for (size_t i = 0; i < n; ++i) {
176 output[i] = bytes[current_byte++];
177 current_byte %= arraysize(bytes);
178 }
179}
180
[email protected]fe2bc6a2009-03-23 16:52:20181std::string MockGetHostName() {
182 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29183}
184
[email protected]a796bcec2010-03-22 17:17:26185template<typename EmulatedClientSocketPool, typename SocketSourceType>
186class CaptureGroupNameSocketPool : public EmulatedClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31187 public:
[email protected]a796bcec2010-03-22 17:17:26188 CaptureGroupNameSocketPool(HttpNetworkSession* session,
189 SocketSourceType* socket_source)
190 : EmulatedClientSocketPool(0, 0, "CaptureGroupNameTestPool",
[email protected]61a86c42010-04-19 22:45:53191 session->host_resolver(), socket_source,
192 NULL) {}
[email protected]d80a4322009-08-14 07:07:49193 const std::string last_group_name_received() const {
194 return last_group_name_;
195 }
196
[email protected]684970b2009-08-14 04:54:46197 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49198 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31199 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31200 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46201 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53202 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31203 last_group_name_ = group_name;
204 return ERR_IO_PENDING;
205 }
[email protected]04e5be32009-06-26 20:00:31206 virtual void CancelRequest(const std::string& group_name,
207 const ClientSocketHandle* handle) { }
208 virtual void ReleaseSocket(const std::string& group_name,
209 ClientSocket* socket) {}
210 virtual void CloseIdleSockets() {}
211 virtual HostResolver* GetHostResolver() const {
212 return NULL;
213 }
214 virtual int IdleSocketCount() const {
215 return 0;
216 }
217 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
218 return 0;
219 }
220 virtual LoadState GetLoadState(const std::string& group_name,
221 const ClientSocketHandle* handle) const {
222 return LOAD_STATE_IDLE;
223 }
[email protected]a796bcec2010-03-22 17:17:26224 virtual base::TimeDelta ConnectionTimeout() const {
225 return base::TimeDelta();
226 }
[email protected]d80a4322009-08-14 07:07:49227
228 private:
[email protected]04e5be32009-06-26 20:00:31229 std::string last_group_name_;
230};
231
[email protected]a796bcec2010-03-22 17:17:26232typedef CaptureGroupNameSocketPool<TCPClientSocketPool, ClientSocketFactory>
233 CaptureGroupNameTCPSocketPool;
234typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool, TCPClientSocketPool>
235 CaptureGroupNameSOCKSSocketPool;
[email protected]231d5a32008-09-13 00:45:27236//-----------------------------------------------------------------------------
237
238TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59239 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40240 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43241 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27242}
243
244TEST_F(HttpNetworkTransactionTest, SimpleGET) {
245 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35246 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
247 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42248 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27249 };
[email protected]31a2bfe2010-02-09 08:03:39250 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
251 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42252 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27253 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
254 EXPECT_EQ("hello world", out.response_data);
255}
256
257// Response with no status line.
258TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
259 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35260 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42261 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27262 };
[email protected]31a2bfe2010-02-09 08:03:39263 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
264 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42265 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27266 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
267 EXPECT_EQ("hello world", out.response_data);
268}
269
270// Allow up to 4 bytes of junk to precede status line.
271TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
272 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35273 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42274 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27275 };
[email protected]31a2bfe2010-02-09 08:03:39276 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
277 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42278 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27279 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
280 EXPECT_EQ("DATA", out.response_data);
281}
282
283// Allow up to 4 bytes of junk to precede status line.
284TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
285 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35286 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42287 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27288 };
[email protected]31a2bfe2010-02-09 08:03:39289 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
290 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42291 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27292 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
293 EXPECT_EQ("DATA", out.response_data);
294}
295
296// Beyond 4 bytes of slop and it should fail to find a status line.
297TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
298 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35299 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42300 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27301 };
[email protected]31a2bfe2010-02-09 08:03:39302 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
303 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42304 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25305 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
306 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27307}
308
309// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
310TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
311 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35312 MockRead("\n"),
313 MockRead("\n"),
314 MockRead("Q"),
315 MockRead("J"),
316 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42317 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27318 };
[email protected]31a2bfe2010-02-09 08:03:39319 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
320 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42321 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27322 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
323 EXPECT_EQ("DATA", out.response_data);
324}
325
326// Close the connection before enough bytes to have a status line.
327TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
328 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35329 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42330 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27331 };
[email protected]31a2bfe2010-02-09 08:03:39332 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
333 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42334 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27335 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
336 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52337}
338
[email protected]f9d44aa2008-09-23 23:57:17339// Simulate a 204 response, lacking a Content-Length header, sent over a
340// persistent connection. The response should still terminate since a 204
341// cannot have a response body.
342TEST_F(HttpNetworkTransactionTest, StopsReading204) {
343 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35344 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
345 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42346 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17347 };
[email protected]31a2bfe2010-02-09 08:03:39348 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
349 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42350 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17351 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
352 EXPECT_EQ("", out.response_data);
353}
354
[email protected]0877e3d2009-10-17 22:29:57355// A simple request using chunked encoding with some extra data after.
356// (Like might be seen in a pipelined response.)
357TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
358 MockRead data_reads[] = {
359 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
360 MockRead("5\r\nHello\r\n"),
361 MockRead("1\r\n"),
362 MockRead(" \r\n"),
363 MockRead("5\r\nworld\r\n"),
364 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
365 MockRead(false, OK),
366 };
[email protected]31a2bfe2010-02-09 08:03:39367 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
368 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57369 EXPECT_EQ(OK, out.rv);
370 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
371 EXPECT_EQ("Hello world", out.response_data);
372}
373
[email protected]ef0faf2e72009-03-05 23:27:23374// Do a request using the HEAD method. Verify that we don't try to read the
375// message body (since HEAD has none).
376TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59377 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40378 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43379 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23380
[email protected]1c773ea12009-04-28 19:58:42381 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23382 request.method = "HEAD";
383 request.url = GURL("http://www.google.com/");
384 request.load_flags = 0;
385
386 MockWrite data_writes1[] = {
387 MockWrite("HEAD / HTTP/1.1\r\n"
388 "Host: www.google.com\r\n"
389 "Connection: keep-alive\r\n"
390 "Content-Length: 0\r\n\r\n"),
391 };
392 MockRead data_reads1[] = {
393 MockRead("HTTP/1.1 404 Not Found\r\n"),
394 MockRead("Server: Blah\r\n"),
395 MockRead("Content-Length: 1234\r\n\r\n"),
396
397 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42398 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23399 };
400
[email protected]31a2bfe2010-02-09 08:03:39401 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
402 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59403 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23404
405 TestCompletionCallback callback1;
406
[email protected]684970b2009-08-14 04:54:46407 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42408 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23409
410 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42411 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23412
[email protected]1c773ea12009-04-28 19:58:42413 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23414 EXPECT_FALSE(response == NULL);
415
416 // Check that the headers got parsed.
417 EXPECT_TRUE(response->headers != NULL);
418 EXPECT_EQ(1234, response->headers->GetContentLength());
419 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
420
421 std::string server_header;
422 void* iter = NULL;
423 bool has_server_header = response->headers->EnumerateHeader(
424 &iter, "Server", &server_header);
425 EXPECT_TRUE(has_server_header);
426 EXPECT_EQ("Blah", server_header);
427
428 // Reading should give EOF right away, since there is no message body
429 // (despite non-zero content-length).
430 std::string response_data;
431 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42432 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23433 EXPECT_EQ("", response_data);
434}
435
initial.commit586acc5fe2008-07-26 22:42:52436TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59437 SessionDependencies session_deps;
438 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52439
440 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35441 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
442 MockRead("hello"),
443 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
444 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42445 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52446 };
[email protected]31a2bfe2010-02-09 08:03:39447 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59448 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52449
450 const char* kExpectedResponseData[] = {
451 "hello", "world"
452 };
453
454 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43455 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52456
[email protected]1c773ea12009-04-28 19:58:42457 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52458 request.method = "GET";
459 request.url = GURL("http://www.google.com/");
460 request.load_flags = 0;
461
462 TestCompletionCallback callback;
463
[email protected]684970b2009-08-14 04:54:46464 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42465 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52466
467 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42468 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52469
[email protected]1c773ea12009-04-28 19:58:42470 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52471 EXPECT_TRUE(response != NULL);
472
473 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25474 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52475
476 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57477 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42478 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25479 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52480 }
481}
482
483TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59484 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40485 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43486 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52487
[email protected]1c773ea12009-04-28 19:58:42488 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52489 request.method = "POST";
490 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42491 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52492 request.upload_data->AppendBytes("foo", 3);
493 request.load_flags = 0;
494
495 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35496 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
497 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
498 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42499 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52500 };
[email protected]31a2bfe2010-02-09 08:03:39501 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59502 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52503
504 TestCompletionCallback callback;
505
[email protected]684970b2009-08-14 04:54:46506 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42507 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52508
509 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42510 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52511
[email protected]1c773ea12009-04-28 19:58:42512 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52513 EXPECT_TRUE(response != NULL);
514
515 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25516 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52517
518 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57519 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42520 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25521 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52522}
523
[email protected]3a2d3662009-03-27 03:49:14524// This test is almost the same as Ignores100 above, but the response contains
525// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57526// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14527TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59528 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40529 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43530 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14531
[email protected]1c773ea12009-04-28 19:58:42532 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14533 request.method = "GET";
534 request.url = GURL("http://www.foo.com/");
535 request.load_flags = 0;
536
537 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57538 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
539 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14540 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42541 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14542 };
[email protected]31a2bfe2010-02-09 08:03:39543 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59544 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14545
546 TestCompletionCallback callback;
547
[email protected]684970b2009-08-14 04:54:46548 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42549 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14550
551 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42552 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14553
[email protected]1c773ea12009-04-28 19:58:42554 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14555 EXPECT_TRUE(response != NULL);
556
557 EXPECT_TRUE(response->headers != NULL);
558 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
559
560 std::string response_data;
561 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42562 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14563 EXPECT_EQ("hello world", response_data);
564}
565
[email protected]ee9410e72010-01-07 01:42:38566TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
567 SessionDependencies session_deps;
568 scoped_ptr<HttpTransaction> trans(
569 new HttpNetworkTransaction(CreateSession(&session_deps)));
570
571 HttpRequestInfo request;
572 request.method = "POST";
573 request.url = GURL("http://www.foo.com/");
574 request.load_flags = 0;
575
576 MockRead data_reads[] = {
577 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
578 MockRead(true, 0),
579 };
[email protected]31a2bfe2010-02-09 08:03:39580 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38581 session_deps.socket_factory.AddSocketDataProvider(&data);
582
583 TestCompletionCallback callback;
584
585 int rv = trans->Start(&request, &callback, NULL);
586 EXPECT_EQ(ERR_IO_PENDING, rv);
587
588 rv = callback.WaitForResult();
589 EXPECT_EQ(OK, rv);
590
591 std::string response_data;
592 rv = ReadTransaction(trans.get(), &response_data);
593 EXPECT_EQ(OK, rv);
594 EXPECT_EQ("", response_data);
595}
596
597TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
598 SessionDependencies session_deps;
599 scoped_ptr<HttpTransaction> trans(
600 new HttpNetworkTransaction(CreateSession(&session_deps)));
601
602 HttpRequestInfo request;
603 request.method = "POST";
604 request.url = GURL("http://www.foo.com/");
605 request.load_flags = 0;
606
607 MockRead data_reads[] = {
608 MockRead(true, 0),
609 };
[email protected]31a2bfe2010-02-09 08:03:39610 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38611 session_deps.socket_factory.AddSocketDataProvider(&data);
612
613 TestCompletionCallback callback;
614
615 int rv = trans->Start(&request, &callback, NULL);
616 EXPECT_EQ(ERR_IO_PENDING, rv);
617
618 rv = callback.WaitForResult();
619 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
620}
621
[email protected]3d2a59b2008-09-26 19:44:25622// read_failure specifies a read failure that should cause the network
623// transaction to resend the request.
624void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
625 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59626 SessionDependencies session_deps;
627 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52628
[email protected]1c773ea12009-04-28 19:58:42629 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52630 request.method = "GET";
631 request.url = GURL("http://www.foo.com/");
632 request.load_flags = 0;
633
634 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35635 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
636 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25637 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52638 };
[email protected]31a2bfe2010-02-09 08:03:39639 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59640 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52641
642 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35643 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
644 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42645 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52646 };
[email protected]31a2bfe2010-02-09 08:03:39647 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59648 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52649
650 const char* kExpectedResponseData[] = {
651 "hello", "world"
652 };
653
654 for (int i = 0; i < 2; ++i) {
655 TestCompletionCallback callback;
656
[email protected]5695b8c2009-09-30 21:36:43657 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52658
[email protected]684970b2009-08-14 04:54:46659 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42660 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52661
662 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42663 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52664
[email protected]1c773ea12009-04-28 19:58:42665 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52666 EXPECT_TRUE(response != NULL);
667
668 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25669 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52670
671 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57672 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42673 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25674 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52675 }
676}
[email protected]3d2a59b2008-09-26 19:44:25677
678TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42679 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25680 KeepAliveConnectionResendRequestTest(read_failure);
681}
682
683TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42684 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25685 KeepAliveConnectionResendRequestTest(read_failure);
686}
687
688TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59689 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40690 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43691 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25692
[email protected]1c773ea12009-04-28 19:58:42693 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25694 request.method = "GET";
695 request.url = GURL("http://www.google.com/");
696 request.load_flags = 0;
697
698 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42699 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35700 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
701 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42702 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25703 };
[email protected]31a2bfe2010-02-09 08:03:39704 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59705 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25706
707 TestCompletionCallback callback;
708
[email protected]684970b2009-08-14 04:54:46709 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42710 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25711
712 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42713 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25714
[email protected]1c773ea12009-04-28 19:58:42715 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25716 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25717}
718
719// What do various browsers do when the server closes a non-keepalive
720// connection without sending any response header or body?
721//
722// IE7: error page
723// Safari 3.1.2 (Windows): error page
724// Firefox 3.0.1: blank page
725// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42726// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
727// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25728TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
729 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42730 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35731 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
732 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42733 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25734 };
[email protected]31a2bfe2010-02-09 08:03:39735 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
736 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42737 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25738}
[email protected]038e9a32008-10-08 22:40:16739
740// Test the request-challenge-retry sequence for basic auth.
741// (basic auth is the easiest to mock, because it has no randomness).
742TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59743 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40744 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43745 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16746
[email protected]1c773ea12009-04-28 19:58:42747 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16748 request.method = "GET";
749 request.url = GURL("http://www.google.com/");
750 request.load_flags = 0;
751
[email protected]f9ee6b52008-11-08 06:46:23752 MockWrite data_writes1[] = {
753 MockWrite("GET / HTTP/1.1\r\n"
754 "Host: www.google.com\r\n"
755 "Connection: keep-alive\r\n\r\n"),
756 };
757
[email protected]038e9a32008-10-08 22:40:16758 MockRead data_reads1[] = {
759 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
760 // Give a couple authenticate options (only the middle one is actually
761 // supported).
[email protected]22927ad2009-09-21 19:56:19762 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16763 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
764 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
765 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
766 // Large content-length -- won't matter, as connection will be reset.
767 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42768 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16769 };
770
771 // After calling trans->RestartWithAuth(), this is the request we should
772 // be issuing -- the final header line contains the credentials.
773 MockWrite data_writes2[] = {
774 MockWrite("GET / HTTP/1.1\r\n"
775 "Host: www.google.com\r\n"
776 "Connection: keep-alive\r\n"
777 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
778 };
779
780 // Lastly, the server responds with the actual content.
781 MockRead data_reads2[] = {
782 MockRead("HTTP/1.0 200 OK\r\n"),
783 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
784 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42785 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16786 };
787
[email protected]31a2bfe2010-02-09 08:03:39788 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
789 data_writes1, arraysize(data_writes1));
790 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
791 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59792 session_deps.socket_factory.AddSocketDataProvider(&data1);
793 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16794
795 TestCompletionCallback callback1;
796
[email protected]684970b2009-08-14 04:54:46797 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42798 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16799
800 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42801 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16802
[email protected]1c773ea12009-04-28 19:58:42803 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16804 EXPECT_FALSE(response == NULL);
805
806 // The password prompt info should have been set in response->auth_challenge.
807 EXPECT_FALSE(response->auth_challenge.get() == NULL);
808
[email protected]71e4573a2009-05-21 22:03:00809 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16810 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
811 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
812
813 TestCompletionCallback callback2;
814
815 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42816 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16817
818 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42819 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16820
821 response = trans->GetResponseInfo();
822 EXPECT_FALSE(response == NULL);
823 EXPECT_TRUE(response->auth_challenge.get() == NULL);
824 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16825}
826
[email protected]861fcd52009-08-26 02:33:46827TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
828 SessionDependencies session_deps;
829 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43830 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46831
832 HttpRequestInfo request;
833 request.method = "GET";
834 request.url = GURL("http://www.google.com/");
835 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
836
837 MockWrite data_writes[] = {
838 MockWrite("GET / HTTP/1.1\r\n"
839 "Host: www.google.com\r\n"
840 "Connection: keep-alive\r\n\r\n"),
841 };
842
843 MockRead data_reads[] = {
844 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
845 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
846 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
847 // Large content-length -- won't matter, as connection will be reset.
848 MockRead("Content-Length: 10000\r\n\r\n"),
849 MockRead(false, ERR_FAILED),
850 };
851
[email protected]31a2bfe2010-02-09 08:03:39852 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
853 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59854 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46855 TestCompletionCallback callback;
856
857 int rv = trans->Start(&request, &callback, NULL);
858 EXPECT_EQ(ERR_IO_PENDING, rv);
859
860 rv = callback.WaitForResult();
861 EXPECT_EQ(0, rv);
862
863 const HttpResponseInfo* response = trans->GetResponseInfo();
864 ASSERT_FALSE(response == NULL);
865 EXPECT_TRUE(response->auth_challenge.get() == NULL);
866}
867
[email protected]2d2697f92009-02-18 21:00:32868// Test the request-challenge-retry sequence for basic auth, over a keep-alive
869// connection.
870TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59871 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40872 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43873 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32874
[email protected]1c773ea12009-04-28 19:58:42875 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32876 request.method = "GET";
877 request.url = GURL("http://www.google.com/");
878 request.load_flags = 0;
879
880 MockWrite data_writes1[] = {
881 MockWrite("GET / HTTP/1.1\r\n"
882 "Host: www.google.com\r\n"
883 "Connection: keep-alive\r\n\r\n"),
884
885 // After calling trans->RestartWithAuth(), this is the request we should
886 // be issuing -- the final header line contains the credentials.
887 MockWrite("GET / HTTP/1.1\r\n"
888 "Host: www.google.com\r\n"
889 "Connection: keep-alive\r\n"
890 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
891 };
892
893 MockRead data_reads1[] = {
894 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
895 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
896 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
897 MockRead("Content-Length: 14\r\n\r\n"),
898 MockRead("Unauthorized\r\n"),
899
900 // Lastly, the server responds with the actual content.
901 MockRead("HTTP/1.1 200 OK\r\n"),
902 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
903 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42904 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32905 };
906
[email protected]31a2bfe2010-02-09 08:03:39907 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
908 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59909 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32910
911 TestCompletionCallback callback1;
912
[email protected]684970b2009-08-14 04:54:46913 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42914 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32915
916 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42917 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32918
[email protected]1c773ea12009-04-28 19:58:42919 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32920 EXPECT_FALSE(response == NULL);
921
922 // The password prompt info should have been set in response->auth_challenge.
923 EXPECT_FALSE(response->auth_challenge.get() == NULL);
924
[email protected]71e4573a2009-05-21 22:03:00925 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32926 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
927 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
928
929 TestCompletionCallback callback2;
930
931 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42932 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32933
934 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42935 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32936
937 response = trans->GetResponseInfo();
938 EXPECT_FALSE(response == NULL);
939 EXPECT_TRUE(response->auth_challenge.get() == NULL);
940 EXPECT_EQ(100, response->headers->GetContentLength());
941}
942
943// Test the request-challenge-retry sequence for basic auth, over a keep-alive
944// connection and with no response body to drain.
945TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59946 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40947 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43948 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32949
[email protected]1c773ea12009-04-28 19:58:42950 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32951 request.method = "GET";
952 request.url = GURL("http://www.google.com/");
953 request.load_flags = 0;
954
955 MockWrite data_writes1[] = {
956 MockWrite("GET / HTTP/1.1\r\n"
957 "Host: www.google.com\r\n"
958 "Connection: keep-alive\r\n\r\n"),
959
960 // After calling trans->RestartWithAuth(), this is the request we should
961 // be issuing -- the final header line contains the credentials.
962 MockWrite("GET / HTTP/1.1\r\n"
963 "Host: www.google.com\r\n"
964 "Connection: keep-alive\r\n"
965 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
966 };
967
[email protected]2d2697f92009-02-18 21:00:32968 MockRead data_reads1[] = {
969 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
970 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:31971 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:32972
973 // Lastly, the server responds with the actual content.
974 MockRead("HTTP/1.1 200 OK\r\n"),
975 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
976 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42977 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32978 };
979
[email protected]31a2bfe2010-02-09 08:03:39980 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
981 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59982 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32983
984 TestCompletionCallback callback1;
985
[email protected]684970b2009-08-14 04:54:46986 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42987 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32988
989 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42990 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32991
[email protected]1c773ea12009-04-28 19:58:42992 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32993 EXPECT_FALSE(response == NULL);
994
995 // The password prompt info should have been set in response->auth_challenge.
996 EXPECT_FALSE(response->auth_challenge.get() == NULL);
997
[email protected]71e4573a2009-05-21 22:03:00998 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32999 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1000 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1001
1002 TestCompletionCallback callback2;
1003
1004 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421005 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321006
1007 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421008 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321009
1010 response = trans->GetResponseInfo();
1011 EXPECT_FALSE(response == NULL);
1012 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1013 EXPECT_EQ(100, response->headers->GetContentLength());
1014}
1015
1016// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1017// connection and with a large response body to drain.
1018TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591019 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401020 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431021 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321022
[email protected]1c773ea12009-04-28 19:58:421023 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321024 request.method = "GET";
1025 request.url = GURL("http://www.google.com/");
1026 request.load_flags = 0;
1027
1028 MockWrite data_writes1[] = {
1029 MockWrite("GET / HTTP/1.1\r\n"
1030 "Host: www.google.com\r\n"
1031 "Connection: keep-alive\r\n\r\n"),
1032
1033 // After calling trans->RestartWithAuth(), this is the request we should
1034 // be issuing -- the final header line contains the credentials.
1035 MockWrite("GET / HTTP/1.1\r\n"
1036 "Host: www.google.com\r\n"
1037 "Connection: keep-alive\r\n"
1038 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1039 };
1040
1041 // Respond with 5 kb of response body.
1042 std::string large_body_string("Unauthorized");
1043 large_body_string.append(5 * 1024, ' ');
1044 large_body_string.append("\r\n");
1045
1046 MockRead data_reads1[] = {
1047 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1048 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1049 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1050 // 5134 = 12 + 5 * 1024 + 2
1051 MockRead("Content-Length: 5134\r\n\r\n"),
1052 MockRead(true, large_body_string.data(), large_body_string.size()),
1053
1054 // Lastly, the server responds with the actual content.
1055 MockRead("HTTP/1.1 200 OK\r\n"),
1056 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1057 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421058 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321059 };
1060
[email protected]31a2bfe2010-02-09 08:03:391061 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1062 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591063 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321064
1065 TestCompletionCallback callback1;
1066
[email protected]684970b2009-08-14 04:54:461067 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421068 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321069
1070 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421071 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321072
[email protected]1c773ea12009-04-28 19:58:421073 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321074 EXPECT_FALSE(response == NULL);
1075
1076 // The password prompt info should have been set in response->auth_challenge.
1077 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1078
[email protected]71e4573a2009-05-21 22:03:001079 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321080 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1081 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1082
1083 TestCompletionCallback callback2;
1084
1085 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421086 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321087
1088 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421089 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321090
1091 response = trans->GetResponseInfo();
1092 EXPECT_FALSE(response == NULL);
1093 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1094 EXPECT_EQ(100, response->headers->GetContentLength());
1095}
1096
1097// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311098// connection, but the server gets impatient and closes the connection.
1099TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1100 SessionDependencies session_deps;
1101 scoped_ptr<HttpTransaction> trans(
1102 new HttpNetworkTransaction(CreateSession(&session_deps)));
1103
1104 HttpRequestInfo request;
1105 request.method = "GET";
1106 request.url = GURL("http://www.google.com/");
1107 request.load_flags = 0;
1108
1109 MockWrite data_writes1[] = {
1110 MockWrite("GET / HTTP/1.1\r\n"
1111 "Host: www.google.com\r\n"
1112 "Connection: keep-alive\r\n\r\n"),
1113 // This simulates the seemingly successful write to a closed connection
1114 // if the bug is not fixed.
1115 MockWrite("GET / HTTP/1.1\r\n"
1116 "Host: www.google.com\r\n"
1117 "Connection: keep-alive\r\n"
1118 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1119 };
1120
1121 MockRead data_reads1[] = {
1122 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1123 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1124 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1125 MockRead("Content-Length: 14\r\n\r\n"),
1126 // Tell MockTCPClientSocket to simulate the server closing the connection.
1127 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1128 MockRead("Unauthorized\r\n"),
1129 MockRead(false, OK), // The server closes the connection.
1130 };
1131
1132 // After calling trans->RestartWithAuth(), this is the request we should
1133 // be issuing -- the final header line contains the credentials.
1134 MockWrite data_writes2[] = {
1135 MockWrite("GET / HTTP/1.1\r\n"
1136 "Host: www.google.com\r\n"
1137 "Connection: keep-alive\r\n"
1138 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1139 };
1140
1141 // Lastly, the server responds with the actual content.
1142 MockRead data_reads2[] = {
1143 MockRead("HTTP/1.1 200 OK\r\n"),
1144 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1145 MockRead("Content-Length: 100\r\n\r\n"),
1146 MockRead(false, OK),
1147 };
1148
[email protected]31a2bfe2010-02-09 08:03:391149 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1150 data_writes1, arraysize(data_writes1));
1151 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1152 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311153 session_deps.socket_factory.AddSocketDataProvider(&data1);
1154 session_deps.socket_factory.AddSocketDataProvider(&data2);
1155
1156 TestCompletionCallback callback1;
1157
1158 int rv = trans->Start(&request, &callback1, NULL);
1159 EXPECT_EQ(ERR_IO_PENDING, rv);
1160
1161 rv = callback1.WaitForResult();
1162 EXPECT_EQ(OK, rv);
1163
1164 const HttpResponseInfo* response = trans->GetResponseInfo();
1165 EXPECT_FALSE(response == NULL);
1166
1167 // The password prompt info should have been set in response->auth_challenge.
1168 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1169
1170 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1171 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1172 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1173
1174 TestCompletionCallback callback2;
1175
1176 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1177 EXPECT_EQ(ERR_IO_PENDING, rv);
1178
1179 rv = callback2.WaitForResult();
1180 EXPECT_EQ(OK, rv);
1181
1182 response = trans->GetResponseInfo();
1183 ASSERT_FALSE(response == NULL);
1184 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1185 EXPECT_EQ(100, response->headers->GetContentLength());
1186}
1187
1188// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321189// proxy connection, when setting up an SSL tunnel.
1190TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1191 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591192 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1193 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321194
[email protected]5695b8c2009-09-30 21:36:431195 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321196
[email protected]1c773ea12009-04-28 19:58:421197 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321198 request.method = "GET";
1199 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461200 // Ensure that proxy authentication is attempted even
1201 // when the no authentication data flag is set.
1202 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321203
1204 // Since we have proxy, should try to establish tunnel.
1205 MockWrite data_writes1[] = {
1206 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451207 "Host: www.google.com\r\n"
1208 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321209
1210 // After calling trans->RestartWithAuth(), this is the request we should
1211 // be issuing -- the final header line contains the credentials.
1212 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1213 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451214 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321215 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1216 };
1217
1218 // The proxy responds to the connect with a 407, using a persistent
1219 // connection.
1220 MockRead data_reads1[] = {
1221 // No credentials.
1222 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1223 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1224 MockRead("Content-Length: 10\r\n\r\n"),
1225 MockRead("0123456789"),
1226
1227 // Wrong credentials (wrong password).
1228 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1229 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1230 MockRead("Content-Length: 10\r\n\r\n"),
1231 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421232 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321233 };
1234
[email protected]31a2bfe2010-02-09 08:03:391235 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1236 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591237 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321238
1239 TestCompletionCallback callback1;
1240
[email protected]684970b2009-08-14 04:54:461241 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421242 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321243
1244 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421245 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321246
[email protected]1c773ea12009-04-28 19:58:421247 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321248 EXPECT_FALSE(response == NULL);
1249
1250 EXPECT_TRUE(response->headers->IsKeepAlive());
1251 EXPECT_EQ(407, response->headers->response_code());
1252 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421253 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321254
1255 // The password prompt info should have been set in response->auth_challenge.
1256 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1257
[email protected]71e4573a2009-05-21 22:03:001258 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321259 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1260 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1261
1262 TestCompletionCallback callback2;
1263
1264 // Wrong password (should be "bar").
1265 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421266 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321267
1268 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421269 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321270
1271 response = trans->GetResponseInfo();
1272 EXPECT_FALSE(response == NULL);
1273
1274 EXPECT_TRUE(response->headers->IsKeepAlive());
1275 EXPECT_EQ(407, response->headers->response_code());
1276 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421277 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321278
1279 // The password prompt info should have been set in response->auth_challenge.
1280 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1281
[email protected]71e4573a2009-05-21 22:03:001282 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321283 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1284 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1285}
1286
[email protected]a8e9b162009-03-12 00:06:441287// Test that we don't read the response body when we fail to establish a tunnel,
1288// even if the user cancels the proxy's auth attempt.
1289TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1290 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591291 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441292
[email protected]e44de5d2009-06-05 20:12:451293 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441294
[email protected]5695b8c2009-09-30 21:36:431295 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441296
[email protected]1c773ea12009-04-28 19:58:421297 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441298 request.method = "GET";
1299 request.url = GURL("https://www.google.com/");
1300 request.load_flags = 0;
1301
1302 // Since we have proxy, should try to establish tunnel.
1303 MockWrite data_writes[] = {
1304 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451305 "Host: www.google.com\r\n"
1306 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441307 };
1308
1309 // The proxy responds to the connect with a 407.
1310 MockRead data_reads[] = {
1311 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1312 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1313 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421314 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441315 };
1316
[email protected]31a2bfe2010-02-09 08:03:391317 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1318 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591319 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441320
1321 TestCompletionCallback callback;
1322
[email protected]684970b2009-08-14 04:54:461323 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421324 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441325
1326 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421327 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441328
[email protected]1c773ea12009-04-28 19:58:421329 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441330 EXPECT_FALSE(response == NULL);
1331
1332 EXPECT_TRUE(response->headers->IsKeepAlive());
1333 EXPECT_EQ(407, response->headers->response_code());
1334 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421335 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441336
1337 std::string response_data;
1338 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421339 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441340}
1341
[email protected]ff007e162009-05-23 09:13:151342void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081343 const MockRead& status, int expected_status) {
1344 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591345 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081346
[email protected]228ff742009-06-05 01:19:591347 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081348
[email protected]5695b8c2009-09-30 21:36:431349 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081350
[email protected]1c773ea12009-04-28 19:58:421351 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081352 request.method = "GET";
1353 request.url = GURL("https://www.google.com/");
1354 request.load_flags = 0;
1355
1356 // Since we have proxy, should try to establish tunnel.
1357 MockWrite data_writes[] = {
1358 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451359 "Host: www.google.com\r\n"
1360 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081361 };
1362
1363 MockRead data_reads[] = {
1364 status,
1365 MockRead("Content-Length: 10\r\n\r\n"),
1366 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421367 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081368 };
1369
[email protected]31a2bfe2010-02-09 08:03:391370 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1371 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591372 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081373
1374 TestCompletionCallback callback;
1375
[email protected]684970b2009-08-14 04:54:461376 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421377 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081378
1379 rv = callback.WaitForResult();
1380 EXPECT_EQ(expected_status, rv);
1381}
1382
[email protected]ff007e162009-05-23 09:13:151383void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081384 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421385 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081386}
1387
1388TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1389 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1390}
1391
1392TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1393 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1394}
1395
1396TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1397 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1398}
1399
1400TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1401 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1402}
1403
1404TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1405 ConnectStatusHelper(
1406 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1407}
1408
1409TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1410 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1411}
1412
1413TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1414 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1415}
1416
1417TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1418 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1419}
1420
1421TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1422 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1423}
1424
1425TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1426 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1427}
1428
1429TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1430 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1431}
1432
1433TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1434 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1435}
1436
1437TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1438 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1439}
1440
1441TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1442 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1443}
1444
1445TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1446 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1447}
1448
1449TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1450 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1451}
1452
1453TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1454 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1455}
1456
1457TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1458 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1459}
1460
1461TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1462 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1463}
1464
1465TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1466 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1467}
1468
1469TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1470 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1471}
1472
1473TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1474 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1475}
1476
1477TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1478 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1479}
1480
1481TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1482 ConnectStatusHelperWithExpectedStatus(
1483 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421484 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081485}
1486
1487TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1488 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1489}
1490
1491TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1492 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1493}
1494
1495TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1496 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1497}
1498
1499TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1500 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1501}
1502
1503TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1504 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1505}
1506
1507TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1508 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1509}
1510
1511TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1512 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1513}
1514
1515TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1516 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1517}
1518
1519TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1520 ConnectStatusHelper(
1521 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1522}
1523
1524TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1525 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1526}
1527
1528TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1529 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1530}
1531
1532TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1533 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1534}
1535
1536TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1537 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1538}
1539
1540TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1541 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1542}
1543
1544TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1545 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1546}
1547
1548TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1549 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1550}
1551
[email protected]038e9a32008-10-08 22:40:161552// Test the flow when both the proxy server AND origin server require
1553// authentication. Again, this uses basic auth for both since that is
1554// the simplest to mock.
1555TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591556 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011557
[email protected]038e9a32008-10-08 22:40:161558 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421559 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431560 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161561
[email protected]1c773ea12009-04-28 19:58:421562 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161563 request.method = "GET";
1564 request.url = GURL("http://www.google.com/");
1565 request.load_flags = 0;
1566
[email protected]f9ee6b52008-11-08 06:46:231567 MockWrite data_writes1[] = {
1568 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1569 "Host: www.google.com\r\n"
1570 "Proxy-Connection: keep-alive\r\n\r\n"),
1571 };
1572
[email protected]038e9a32008-10-08 22:40:161573 MockRead data_reads1[] = {
1574 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1575 // Give a couple authenticate options (only the middle one is actually
1576 // supported).
[email protected]22927ad2009-09-21 19:56:191577 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161578 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1579 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1580 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1581 // Large content-length -- won't matter, as connection will be reset.
1582 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421583 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161584 };
1585
1586 // After calling trans->RestartWithAuth() the first time, this is the
1587 // request we should be issuing -- the final header line contains the
1588 // proxy's credentials.
1589 MockWrite data_writes2[] = {
1590 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1591 "Host: www.google.com\r\n"
1592 "Proxy-Connection: keep-alive\r\n"
1593 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1594 };
1595
1596 // Now the proxy server lets the request pass through to origin server.
1597 // The origin server responds with a 401.
1598 MockRead data_reads2[] = {
1599 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1600 // Note: We are using the same realm-name as the proxy server. This is
1601 // completely valid, as realms are unique across hosts.
1602 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1603 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1604 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421605 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161606 };
1607
1608 // After calling trans->RestartWithAuth() the second time, we should send
1609 // the credentials for both the proxy and origin server.
1610 MockWrite data_writes3[] = {
1611 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1612 "Host: www.google.com\r\n"
1613 "Proxy-Connection: keep-alive\r\n"
1614 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1615 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1616 };
1617
1618 // Lastly we get the desired content.
1619 MockRead data_reads3[] = {
1620 MockRead("HTTP/1.0 200 OK\r\n"),
1621 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1622 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421623 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161624 };
1625
[email protected]31a2bfe2010-02-09 08:03:391626 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1627 data_writes1, arraysize(data_writes1));
1628 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1629 data_writes2, arraysize(data_writes2));
1630 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1631 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591632 session_deps.socket_factory.AddSocketDataProvider(&data1);
1633 session_deps.socket_factory.AddSocketDataProvider(&data2);
1634 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161635
1636 TestCompletionCallback callback1;
1637
[email protected]684970b2009-08-14 04:54:461638 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421639 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161640
1641 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421642 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161643
[email protected]1c773ea12009-04-28 19:58:421644 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161645 EXPECT_FALSE(response == NULL);
1646
1647 // The password prompt info should have been set in response->auth_challenge.
1648 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1649
[email protected]71e4573a2009-05-21 22:03:001650 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161651 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1652 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1653
1654 TestCompletionCallback callback2;
1655
1656 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421657 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161658
1659 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421660 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161661
1662 response = trans->GetResponseInfo();
1663 EXPECT_FALSE(response == NULL);
1664 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1665
[email protected]71e4573a2009-05-21 22:03:001666 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161667 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1668 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1669
1670 TestCompletionCallback callback3;
1671
1672 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421673 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161674
1675 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421676 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161677
1678 response = trans->GetResponseInfo();
1679 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1680 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161681}
[email protected]4ddaf2502008-10-23 18:26:191682
[email protected]ea9dc9a2009-09-05 00:43:321683// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1684// can't hook into its internals to cause it to generate predictable NTLM
1685// authorization headers.
1686#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291687// The NTLM authentication unit tests were generated by capturing the HTTP
1688// requests and responses using Fiddler 2 and inspecting the generated random
1689// bytes in the debugger.
1690
1691// Enter the correct password and authenticate successfully.
1692TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421693 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201694 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591695 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401696 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431697 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241698
[email protected]1c773ea12009-04-28 19:58:421699 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241700 request.method = "GET";
1701 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1702 request.load_flags = 0;
1703
1704 MockWrite data_writes1[] = {
1705 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1706 "Host: 172.22.68.17\r\n"
1707 "Connection: keep-alive\r\n\r\n"),
1708 };
1709
1710 MockRead data_reads1[] = {
1711 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1712 // Negotiate and NTLM are often requested together. We only support NTLM.
1713 MockRead("WWW-Authenticate: Negotiate\r\n"),
1714 MockRead("WWW-Authenticate: NTLM\r\n"),
1715 MockRead("Connection: close\r\n"),
1716 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361717 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241718 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421719 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241720 };
1721
1722 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221723 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241724 // request we should be issuing -- the final header line contains a Type
1725 // 1 message.
1726 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1727 "Host: 172.22.68.17\r\n"
1728 "Connection: keep-alive\r\n"
1729 "Authorization: NTLM "
1730 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1731
1732 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1733 // (the credentials for the origin server). The second request continues
1734 // on the same connection.
1735 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1736 "Host: 172.22.68.17\r\n"
1737 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291738 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1739 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1740 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1741 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1742 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241743 };
1744
1745 MockRead data_reads2[] = {
1746 // The origin server responds with a Type 2 message.
1747 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1748 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291749 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241750 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1751 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1752 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1753 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1754 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1755 "BtAAAAAAA=\r\n"),
1756 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361757 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241758 MockRead("You are not authorized to view this page\r\n"),
1759
1760 // Lastly we get the desired content.
1761 MockRead("HTTP/1.1 200 OK\r\n"),
1762 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1763 MockRead("Content-Length: 13\r\n\r\n"),
1764 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421765 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241766 };
1767
[email protected]31a2bfe2010-02-09 08:03:391768 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1769 data_writes1, arraysize(data_writes1));
1770 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1771 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591772 session_deps.socket_factory.AddSocketDataProvider(&data1);
1773 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241774
1775 TestCompletionCallback callback1;
1776
[email protected]684970b2009-08-14 04:54:461777 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421778 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241779
1780 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421781 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241782
[email protected]0757e7702009-03-27 04:00:221783 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1784 TestCompletionCallback callback2;
1785 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421786 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221787 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421788 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221789 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1790
[email protected]1c773ea12009-04-28 19:58:421791 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241792 EXPECT_FALSE(response == NULL);
1793
1794 // The password prompt info should have been set in response->auth_challenge.
1795 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1796
[email protected]71e4573a2009-05-21 22:03:001797 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241798 EXPECT_EQ(L"", response->auth_challenge->realm);
1799 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1800
[email protected]0757e7702009-03-27 04:00:221801 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241802
[email protected]0757e7702009-03-27 04:00:221803 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421804 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241805
[email protected]0757e7702009-03-27 04:00:221806 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421807 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241808
1809 response = trans->GetResponseInfo();
1810 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1811 EXPECT_EQ(13, response->headers->GetContentLength());
1812}
1813
[email protected]385a4672009-03-11 22:21:291814// Enter a wrong password, and then the correct one.
1815TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421816 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201817 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591818 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401819 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431820 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291821
[email protected]1c773ea12009-04-28 19:58:421822 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291823 request.method = "GET";
1824 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1825 request.load_flags = 0;
1826
1827 MockWrite data_writes1[] = {
1828 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1829 "Host: 172.22.68.17\r\n"
1830 "Connection: keep-alive\r\n\r\n"),
1831 };
1832
1833 MockRead data_reads1[] = {
1834 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1835 // Negotiate and NTLM are often requested together. We only support NTLM.
1836 MockRead("WWW-Authenticate: Negotiate\r\n"),
1837 MockRead("WWW-Authenticate: NTLM\r\n"),
1838 MockRead("Connection: close\r\n"),
1839 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361840 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291841 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421842 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291843 };
1844
1845 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221846 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291847 // request we should be issuing -- the final header line contains a Type
1848 // 1 message.
1849 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1850 "Host: 172.22.68.17\r\n"
1851 "Connection: keep-alive\r\n"
1852 "Authorization: NTLM "
1853 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1854
1855 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1856 // (the credentials for the origin server). The second request continues
1857 // on the same connection.
1858 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1859 "Host: 172.22.68.17\r\n"
1860 "Connection: keep-alive\r\n"
1861 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1862 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1863 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1864 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1865 "4Ww7b7E=\r\n\r\n"),
1866 };
1867
1868 MockRead data_reads2[] = {
1869 // The origin server responds with a Type 2 message.
1870 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1871 MockRead("WWW-Authenticate: NTLM "
1872 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1873 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1874 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1875 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1876 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1877 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1878 "BtAAAAAAA=\r\n"),
1879 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361880 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291881 MockRead("You are not authorized to view this page\r\n"),
1882
1883 // Wrong password.
1884 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1885 MockRead("WWW-Authenticate: Negotiate\r\n"),
1886 MockRead("WWW-Authenticate: NTLM\r\n"),
1887 MockRead("Connection: close\r\n"),
1888 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361889 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291890 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421891 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291892 };
1893
1894 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221895 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291896 // request we should be issuing -- the final header line contains a Type
1897 // 1 message.
1898 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1899 "Host: 172.22.68.17\r\n"
1900 "Connection: keep-alive\r\n"
1901 "Authorization: NTLM "
1902 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1903
1904 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1905 // (the credentials for the origin server). The second request continues
1906 // on the same connection.
1907 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1908 "Host: 172.22.68.17\r\n"
1909 "Connection: keep-alive\r\n"
1910 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1911 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1912 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1913 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1914 "+4MUm7c=\r\n\r\n"),
1915 };
1916
1917 MockRead data_reads3[] = {
1918 // The origin server responds with a Type 2 message.
1919 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1920 MockRead("WWW-Authenticate: NTLM "
1921 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1922 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1923 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1924 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1925 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1926 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1927 "BtAAAAAAA=\r\n"),
1928 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361929 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291930 MockRead("You are not authorized to view this page\r\n"),
1931
1932 // Lastly we get the desired content.
1933 MockRead("HTTP/1.1 200 OK\r\n"),
1934 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1935 MockRead("Content-Length: 13\r\n\r\n"),
1936 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421937 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291938 };
1939
[email protected]31a2bfe2010-02-09 08:03:391940 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1941 data_writes1, arraysize(data_writes1));
1942 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1943 data_writes2, arraysize(data_writes2));
1944 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1945 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591946 session_deps.socket_factory.AddSocketDataProvider(&data1);
1947 session_deps.socket_factory.AddSocketDataProvider(&data2);
1948 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:291949
1950 TestCompletionCallback callback1;
1951
[email protected]684970b2009-08-14 04:54:461952 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421953 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291954
1955 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421956 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291957
[email protected]0757e7702009-03-27 04:00:221958 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291959 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221960 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421961 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291962 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421963 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221964 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291965
[email protected]1c773ea12009-04-28 19:58:421966 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291967 EXPECT_FALSE(response == NULL);
1968
1969 // The password prompt info should have been set in response->auth_challenge.
1970 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1971
[email protected]71e4573a2009-05-21 22:03:001972 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291973 EXPECT_EQ(L"", response->auth_challenge->realm);
1974 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1975
1976 TestCompletionCallback callback3;
1977
[email protected]0757e7702009-03-27 04:00:221978 // Enter the wrong password.
1979 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421980 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291981
1982 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421983 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291984
[email protected]0757e7702009-03-27 04:00:221985 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1986 TestCompletionCallback callback4;
1987 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421988 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221989 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421990 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221991 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1992
1993 response = trans->GetResponseInfo();
1994 EXPECT_FALSE(response == NULL);
1995
1996 // The password prompt info should have been set in response->auth_challenge.
1997 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1998
[email protected]71e4573a2009-05-21 22:03:001999 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222000 EXPECT_EQ(L"", response->auth_challenge->realm);
2001 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2002
2003 TestCompletionCallback callback5;
2004
2005 // Now enter the right password.
2006 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422007 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222008
2009 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422010 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222011
[email protected]385a4672009-03-11 22:21:292012 response = trans->GetResponseInfo();
2013 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2014 EXPECT_EQ(13, response->headers->GetContentLength());
2015}
[email protected]ea9dc9a2009-09-05 00:43:322016#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292017
[email protected]4ddaf2502008-10-23 18:26:192018// Test reading a server response which has only headers, and no body.
2019// After some maximum number of bytes is consumed, the transaction should
2020// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2021TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592022 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402023 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432024 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192025
[email protected]1c773ea12009-04-28 19:58:422026 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192027 request.method = "GET";
2028 request.url = GURL("http://www.google.com/");
2029 request.load_flags = 0;
2030
[email protected]b75b7b2f2009-10-06 00:54:532031 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432032 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532033 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192034
2035 MockRead data_reads[] = {
2036 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432037 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192038 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422039 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192040 };
[email protected]31a2bfe2010-02-09 08:03:392041 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592042 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192043
2044 TestCompletionCallback callback;
2045
[email protected]684970b2009-08-14 04:54:462046 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422047 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192048
2049 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422050 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192051
[email protected]1c773ea12009-04-28 19:58:422052 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192053 EXPECT_TRUE(response == NULL);
2054}
[email protected]f4e426b2008-11-05 00:24:492055
2056// Make sure that we don't try to reuse a TCPClientSocket when failing to
2057// establish tunnel.
2058// http://code.google.com/p/chromium/issues/detail?id=3772
2059TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2060 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592061 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012062
[email protected]228ff742009-06-05 01:19:592063 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492064
[email protected]5695b8c2009-09-30 21:36:432065 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492066
[email protected]1c773ea12009-04-28 19:58:422067 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492068 request.method = "GET";
2069 request.url = GURL("https://www.google.com/");
2070 request.load_flags = 0;
2071
2072 // Since we have proxy, should try to establish tunnel.
2073 MockWrite data_writes1[] = {
2074 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452075 "Host: www.google.com\r\n"
2076 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492077 };
2078
[email protected]77848d12008-11-14 00:00:222079 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492080 // connection. Usually a proxy would return 501 (not implemented),
2081 // or 200 (tunnel established).
2082 MockRead data_reads1[] = {
2083 MockRead("HTTP/1.1 404 Not Found\r\n"),
2084 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422085 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492086 };
2087
[email protected]31a2bfe2010-02-09 08:03:392088 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2089 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592090 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492091
2092 TestCompletionCallback callback1;
2093
[email protected]684970b2009-08-14 04:54:462094 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422095 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492096
2097 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422098 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492099
[email protected]1c773ea12009-04-28 19:58:422100 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082101 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492102
[email protected]b4404c02009-04-10 16:38:522103 // Empty the current queue. This is necessary because idle sockets are
2104 // added to the connection pool asynchronously with a PostTask.
2105 MessageLoop::current()->RunAllPending();
2106
[email protected]f4e426b2008-11-05 00:24:492107 // We now check to make sure the TCPClientSocket was not added back to
2108 // the pool.
[email protected]a937a06d2009-08-19 21:19:242109 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492110 trans.reset();
[email protected]b4404c02009-04-10 16:38:522111 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492112 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242113 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492114}
[email protected]372d34a2008-11-05 21:30:512115
[email protected]1b157c02009-04-21 01:55:402116// Make sure that we recycle a socket after reading all of the response body.
2117TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592118 SessionDependencies session_deps;
2119 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402120
[email protected]5695b8c2009-09-30 21:36:432121 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402122
[email protected]1c773ea12009-04-28 19:58:422123 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402124 request.method = "GET";
2125 request.url = GURL("http://www.google.com/");
2126 request.load_flags = 0;
2127
2128 MockRead data_reads[] = {
2129 // A part of the response body is received with the response headers.
2130 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2131 // The rest of the response body is received in two parts.
2132 MockRead("lo"),
2133 MockRead(" world"),
2134 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422135 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402136 };
2137
[email protected]31a2bfe2010-02-09 08:03:392138 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592139 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402140
2141 TestCompletionCallback callback;
2142
[email protected]684970b2009-08-14 04:54:462143 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422144 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402145
2146 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422147 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402148
[email protected]1c773ea12009-04-28 19:58:422149 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402150 EXPECT_TRUE(response != NULL);
2151
2152 EXPECT_TRUE(response->headers != NULL);
2153 std::string status_line = response->headers->GetStatusLine();
2154 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2155
[email protected]a937a06d2009-08-19 21:19:242156 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402157
2158 std::string response_data;
2159 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422160 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402161 EXPECT_EQ("hello world", response_data);
2162
2163 // Empty the current queue. This is necessary because idle sockets are
2164 // added to the connection pool asynchronously with a PostTask.
2165 MessageLoop::current()->RunAllPending();
2166
2167 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242168 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402169}
2170
[email protected]b4404c02009-04-10 16:38:522171// Make sure that we recycle a socket after a zero-length response.
2172// http://crbug.com/9880
2173TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592174 SessionDependencies session_deps;
2175 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522176
[email protected]5695b8c2009-09-30 21:36:432177 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522178
[email protected]1c773ea12009-04-28 19:58:422179 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522180 request.method = "GET";
2181 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2182 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2183 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2184 "rt=prt.2642,ol.2649,xjs.2951");
2185 request.load_flags = 0;
2186
2187 MockRead data_reads[] = {
2188 MockRead("HTTP/1.1 204 No Content\r\n"
2189 "Content-Length: 0\r\n"
2190 "Content-Type: text/html\r\n\r\n"),
2191 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422192 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522193 };
2194
[email protected]31a2bfe2010-02-09 08:03:392195 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592196 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522197
2198 TestCompletionCallback callback;
2199
[email protected]684970b2009-08-14 04:54:462200 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422201 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522202
2203 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422204 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522205
[email protected]1c773ea12009-04-28 19:58:422206 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522207 EXPECT_TRUE(response != NULL);
2208
2209 EXPECT_TRUE(response->headers != NULL);
2210 std::string status_line = response->headers->GetStatusLine();
2211 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2212
[email protected]a937a06d2009-08-19 21:19:242213 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522214
2215 std::string response_data;
2216 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422217 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522218 EXPECT_EQ("", response_data);
2219
2220 // Empty the current queue. This is necessary because idle sockets are
2221 // added to the connection pool asynchronously with a PostTask.
2222 MessageLoop::current()->RunAllPending();
2223
2224 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242225 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522226}
2227
[email protected]372d34a2008-11-05 21:30:512228TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422229 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512230 // Transaction 1: a GET request that succeeds. The socket is recycled
2231 // after use.
2232 request[0].method = "GET";
2233 request[0].url = GURL("http://www.google.com/");
2234 request[0].load_flags = 0;
2235 // Transaction 2: a POST request. Reuses the socket kept alive from
2236 // transaction 1. The first attempts fails when writing the POST data.
2237 // This causes the transaction to retry with a new socket. The second
2238 // attempt succeeds.
2239 request[1].method = "POST";
2240 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422241 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512242 request[1].upload_data->AppendBytes("foo", 3);
2243 request[1].load_flags = 0;
2244
[email protected]228ff742009-06-05 01:19:592245 SessionDependencies session_deps;
2246 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512247
2248 // The first socket is used for transaction 1 and the first attempt of
2249 // transaction 2.
2250
2251 // The response of transaction 1.
2252 MockRead data_reads1[] = {
2253 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2254 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422255 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512256 };
2257 // The mock write results of transaction 1 and the first attempt of
2258 // transaction 2.
2259 MockWrite data_writes1[] = {
2260 MockWrite(false, 64), // GET
2261 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422262 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512263 };
[email protected]31a2bfe2010-02-09 08:03:392264 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2265 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512266
2267 // The second socket is used for the second attempt of transaction 2.
2268
2269 // The response of transaction 2.
2270 MockRead data_reads2[] = {
2271 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2272 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422273 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512274 };
2275 // The mock write results of the second attempt of transaction 2.
2276 MockWrite data_writes2[] = {
2277 MockWrite(false, 93), // POST
2278 MockWrite(false, 3), // POST data
2279 };
[email protected]31a2bfe2010-02-09 08:03:392280 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2281 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512282
[email protected]5ecc992a42009-11-11 01:41:592283 session_deps.socket_factory.AddSocketDataProvider(&data1);
2284 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512285
2286 const char* kExpectedResponseData[] = {
2287 "hello world", "welcome"
2288 };
2289
2290 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422291 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432292 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512293
2294 TestCompletionCallback callback;
2295
[email protected]684970b2009-08-14 04:54:462296 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422297 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512298
2299 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422300 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512301
[email protected]1c773ea12009-04-28 19:58:422302 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512303 EXPECT_TRUE(response != NULL);
2304
2305 EXPECT_TRUE(response->headers != NULL);
2306 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2307
2308 std::string response_data;
2309 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422310 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512311 EXPECT_EQ(kExpectedResponseData[i], response_data);
2312 }
2313}
[email protected]f9ee6b52008-11-08 06:46:232314
2315// Test the request-challenge-retry sequence for basic auth when there is
2316// an identity in the URL. The request should be sent as normal, but when
2317// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322318TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592319 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402320 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432321 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232322
[email protected]1c773ea12009-04-28 19:58:422323 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232324 request.method = "GET";
2325 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292326 request.url = GURL("http://foo:b@[email protected]/");
2327
2328 // The password contains an escaped character -- for this test to pass it
2329 // will need to be unescaped by HttpNetworkTransaction.
2330 EXPECT_EQ("b%40r", request.url.password());
2331
[email protected]ea9dc9a2009-09-05 00:43:322332 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232333
2334 MockWrite data_writes1[] = {
2335 MockWrite("GET / HTTP/1.1\r\n"
2336 "Host: www.google.com\r\n"
2337 "Connection: keep-alive\r\n\r\n"),
2338 };
2339
2340 MockRead data_reads1[] = {
2341 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2342 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2343 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422344 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232345 };
2346
2347 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322348 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232349 MockWrite data_writes2[] = {
2350 MockWrite("GET / HTTP/1.1\r\n"
2351 "Host: www.google.com\r\n"
2352 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292353 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232354 };
2355
2356 MockRead data_reads2[] = {
2357 MockRead("HTTP/1.0 200 OK\r\n"),
2358 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422359 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232360 };
2361
[email protected]31a2bfe2010-02-09 08:03:392362 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2363 data_writes1, arraysize(data_writes1));
2364 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2365 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592366 session_deps.socket_factory.AddSocketDataProvider(&data1);
2367 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232368
2369 TestCompletionCallback callback1;
2370
[email protected]684970b2009-08-14 04:54:462371 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422372 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232373
2374 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422375 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232376
[email protected]0757e7702009-03-27 04:00:222377 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2378 TestCompletionCallback callback2;
2379 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422380 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222381 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422382 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222383 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2384
[email protected]1c773ea12009-04-28 19:58:422385 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232386 EXPECT_FALSE(response == NULL);
2387
2388 // There is no challenge info, since the identity in URL worked.
2389 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2390
2391 EXPECT_EQ(100, response->headers->GetContentLength());
2392
2393 // Empty the current queue.
2394 MessageLoop::current()->RunAllPending();
2395}
2396
[email protected]ea9dc9a2009-09-05 00:43:322397// Test the request-challenge-retry sequence for basic auth when there is
2398// an incorrect identity in the URL. The identity from the URL should be used
2399// only once.
2400TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2401 SessionDependencies session_deps;
2402 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432403 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322404
2405 HttpRequestInfo request;
2406 request.method = "GET";
2407 // Note: the URL has a username:password in it. The password "baz" is
2408 // wrong (should be "bar").
2409 request.url = GURL("http://foo:[email protected]/");
2410
2411 request.load_flags = LOAD_NORMAL;
2412
2413 MockWrite data_writes1[] = {
2414 MockWrite("GET / HTTP/1.1\r\n"
2415 "Host: www.google.com\r\n"
2416 "Connection: keep-alive\r\n\r\n"),
2417 };
2418
2419 MockRead data_reads1[] = {
2420 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2421 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2422 MockRead("Content-Length: 10\r\n\r\n"),
2423 MockRead(false, ERR_FAILED),
2424 };
2425
2426 // After the challenge above, the transaction will be restarted using the
2427 // identity from the url (foo, baz) to answer the challenge.
2428 MockWrite data_writes2[] = {
2429 MockWrite("GET / HTTP/1.1\r\n"
2430 "Host: www.google.com\r\n"
2431 "Connection: keep-alive\r\n"
2432 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2433 };
2434
2435 MockRead data_reads2[] = {
2436 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2437 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2438 MockRead("Content-Length: 10\r\n\r\n"),
2439 MockRead(false, ERR_FAILED),
2440 };
2441
2442 // After the challenge above, the transaction will be restarted using the
2443 // identity supplied by the user (foo, bar) to answer the challenge.
2444 MockWrite data_writes3[] = {
2445 MockWrite("GET / HTTP/1.1\r\n"
2446 "Host: www.google.com\r\n"
2447 "Connection: keep-alive\r\n"
2448 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2449 };
2450
2451 MockRead data_reads3[] = {
2452 MockRead("HTTP/1.0 200 OK\r\n"),
2453 MockRead("Content-Length: 100\r\n\r\n"),
2454 MockRead(false, OK),
2455 };
2456
[email protected]31a2bfe2010-02-09 08:03:392457 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2458 data_writes1, arraysize(data_writes1));
2459 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2460 data_writes2, arraysize(data_writes2));
2461 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2462 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592463 session_deps.socket_factory.AddSocketDataProvider(&data1);
2464 session_deps.socket_factory.AddSocketDataProvider(&data2);
2465 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322466
2467 TestCompletionCallback callback1;
2468
2469 int rv = trans->Start(&request, &callback1, NULL);
2470 EXPECT_EQ(ERR_IO_PENDING, rv);
2471
2472 rv = callback1.WaitForResult();
2473 EXPECT_EQ(OK, rv);
2474
2475 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2476 TestCompletionCallback callback2;
2477 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2478 EXPECT_EQ(ERR_IO_PENDING, rv);
2479 rv = callback2.WaitForResult();
2480 EXPECT_EQ(OK, rv);
2481 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2482
2483 const HttpResponseInfo* response = trans->GetResponseInfo();
2484 EXPECT_FALSE(response == NULL);
2485 // The password prompt info should have been set in response->auth_challenge.
2486 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2487
2488 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2489 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2490 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2491
2492 TestCompletionCallback callback3;
2493 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2494 EXPECT_EQ(ERR_IO_PENDING, rv);
2495 rv = callback3.WaitForResult();
2496 EXPECT_EQ(OK, rv);
2497 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2498
2499 response = trans->GetResponseInfo();
2500 EXPECT_FALSE(response == NULL);
2501
2502 // There is no challenge info, since the identity worked.
2503 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2504
2505 EXPECT_EQ(100, response->headers->GetContentLength());
2506
2507 // Empty the current queue.
2508 MessageLoop::current()->RunAllPending();
2509}
2510
[email protected]f9ee6b52008-11-08 06:46:232511// Test that previously tried username/passwords for a realm get re-used.
2512TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592513 SessionDependencies session_deps;
2514 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232515
2516 // Transaction 1: authenticate (foo, bar) on MyRealm1
2517 {
[email protected]5695b8c2009-09-30 21:36:432518 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232519
[email protected]1c773ea12009-04-28 19:58:422520 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232521 request.method = "GET";
2522 request.url = GURL("http://www.google.com/x/y/z");
2523 request.load_flags = 0;
2524
2525 MockWrite data_writes1[] = {
2526 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2527 "Host: www.google.com\r\n"
2528 "Connection: keep-alive\r\n\r\n"),
2529 };
2530
2531 MockRead data_reads1[] = {
2532 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2533 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2534 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422535 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232536 };
2537
2538 // Resend with authorization (username=foo, password=bar)
2539 MockWrite data_writes2[] = {
2540 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2541 "Host: www.google.com\r\n"
2542 "Connection: keep-alive\r\n"
2543 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2544 };
2545
2546 // Sever accepts the authorization.
2547 MockRead data_reads2[] = {
2548 MockRead("HTTP/1.0 200 OK\r\n"),
2549 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422550 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232551 };
2552
[email protected]31a2bfe2010-02-09 08:03:392553 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2554 data_writes1, arraysize(data_writes1));
2555 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2556 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592557 session_deps.socket_factory.AddSocketDataProvider(&data1);
2558 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232559
2560 TestCompletionCallback callback1;
2561
[email protected]684970b2009-08-14 04:54:462562 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422563 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232564
2565 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422566 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232567
[email protected]1c773ea12009-04-28 19:58:422568 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232569 EXPECT_FALSE(response == NULL);
2570
2571 // The password prompt info should have been set in
2572 // response->auth_challenge.
2573 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2574
[email protected]71e4573a2009-05-21 22:03:002575 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232576 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2577 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2578
2579 TestCompletionCallback callback2;
2580
2581 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422582 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232583
2584 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422585 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232586
2587 response = trans->GetResponseInfo();
2588 EXPECT_FALSE(response == NULL);
2589 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2590 EXPECT_EQ(100, response->headers->GetContentLength());
2591 }
2592
2593 // ------------------------------------------------------------------------
2594
2595 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2596 {
[email protected]5695b8c2009-09-30 21:36:432597 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232598
[email protected]1c773ea12009-04-28 19:58:422599 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232600 request.method = "GET";
2601 // Note that Transaction 1 was at /x/y/z, so this is in the same
2602 // protection space as MyRealm1.
2603 request.url = GURL("http://www.google.com/x/y/a/b");
2604 request.load_flags = 0;
2605
2606 MockWrite data_writes1[] = {
2607 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2608 "Host: www.google.com\r\n"
2609 "Connection: keep-alive\r\n"
2610 // Send preemptive authorization for MyRealm1
2611 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2612 };
2613
2614 // The server didn't like the preemptive authorization, and
2615 // challenges us for a different realm (MyRealm2).
2616 MockRead data_reads1[] = {
2617 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2618 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2619 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422620 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232621 };
2622
2623 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2624 MockWrite data_writes2[] = {
2625 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2626 "Host: www.google.com\r\n"
2627 "Connection: keep-alive\r\n"
2628 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2629 };
2630
2631 // Sever accepts the authorization.
2632 MockRead data_reads2[] = {
2633 MockRead("HTTP/1.0 200 OK\r\n"),
2634 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422635 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232636 };
2637
[email protected]31a2bfe2010-02-09 08:03:392638 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2639 data_writes1, arraysize(data_writes1));
2640 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2641 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592642 session_deps.socket_factory.AddSocketDataProvider(&data1);
2643 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232644
2645 TestCompletionCallback callback1;
2646
[email protected]684970b2009-08-14 04:54:462647 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422648 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232649
2650 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422651 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232652
[email protected]1c773ea12009-04-28 19:58:422653 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232654 EXPECT_FALSE(response == NULL);
2655
2656 // The password prompt info should have been set in
2657 // response->auth_challenge.
2658 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2659
[email protected]71e4573a2009-05-21 22:03:002660 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232661 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2662 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2663
2664 TestCompletionCallback callback2;
2665
2666 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422667 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232668
2669 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422670 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232671
2672 response = trans->GetResponseInfo();
2673 EXPECT_FALSE(response == NULL);
2674 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2675 EXPECT_EQ(100, response->headers->GetContentLength());
2676 }
2677
2678 // ------------------------------------------------------------------------
2679
2680 // Transaction 3: Resend a request in MyRealm's protection space --
2681 // succeed with preemptive authorization.
2682 {
[email protected]5695b8c2009-09-30 21:36:432683 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232684
[email protected]1c773ea12009-04-28 19:58:422685 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232686 request.method = "GET";
2687 request.url = GURL("http://www.google.com/x/y/z2");
2688 request.load_flags = 0;
2689
2690 MockWrite data_writes1[] = {
2691 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2692 "Host: www.google.com\r\n"
2693 "Connection: keep-alive\r\n"
2694 // The authorization for MyRealm1 gets sent preemptively
2695 // (since the url is in the same protection space)
2696 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2697 };
2698
2699 // Sever accepts the preemptive authorization
2700 MockRead data_reads1[] = {
2701 MockRead("HTTP/1.0 200 OK\r\n"),
2702 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422703 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232704 };
2705
[email protected]31a2bfe2010-02-09 08:03:392706 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2707 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592708 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232709
2710 TestCompletionCallback callback1;
2711
[email protected]684970b2009-08-14 04:54:462712 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422713 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232714
2715 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422716 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232717
[email protected]1c773ea12009-04-28 19:58:422718 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232719 EXPECT_FALSE(response == NULL);
2720
2721 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2722 EXPECT_EQ(100, response->headers->GetContentLength());
2723 }
2724
2725 // ------------------------------------------------------------------------
2726
2727 // Transaction 4: request another URL in MyRealm (however the
2728 // url is not known to belong to the protection space, so no pre-auth).
2729 {
[email protected]5695b8c2009-09-30 21:36:432730 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232731
[email protected]1c773ea12009-04-28 19:58:422732 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232733 request.method = "GET";
2734 request.url = GURL("http://www.google.com/x/1");
2735 request.load_flags = 0;
2736
2737 MockWrite data_writes1[] = {
2738 MockWrite("GET /x/1 HTTP/1.1\r\n"
2739 "Host: www.google.com\r\n"
2740 "Connection: keep-alive\r\n\r\n"),
2741 };
2742
2743 MockRead data_reads1[] = {
2744 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2745 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2746 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422747 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232748 };
2749
2750 // Resend with authorization from MyRealm's cache.
2751 MockWrite data_writes2[] = {
2752 MockWrite("GET /x/1 HTTP/1.1\r\n"
2753 "Host: www.google.com\r\n"
2754 "Connection: keep-alive\r\n"
2755 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2756 };
2757
2758 // Sever accepts the authorization.
2759 MockRead data_reads2[] = {
2760 MockRead("HTTP/1.0 200 OK\r\n"),
2761 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422762 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232763 };
2764
[email protected]31a2bfe2010-02-09 08:03:392765 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2766 data_writes1, arraysize(data_writes1));
2767 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2768 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592769 session_deps.socket_factory.AddSocketDataProvider(&data1);
2770 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232771
2772 TestCompletionCallback callback1;
2773
[email protected]684970b2009-08-14 04:54:462774 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422775 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232776
2777 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422778 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232779
[email protected]0757e7702009-03-27 04:00:222780 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2781 TestCompletionCallback callback2;
2782 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422783 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222784 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422785 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222786 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2787
[email protected]1c773ea12009-04-28 19:58:422788 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232789 EXPECT_FALSE(response == NULL);
2790 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2791 EXPECT_EQ(100, response->headers->GetContentLength());
2792 }
2793
2794 // ------------------------------------------------------------------------
2795
2796 // Transaction 5: request a URL in MyRealm, but the server rejects the
2797 // cached identity. Should invalidate and re-prompt.
2798 {
[email protected]5695b8c2009-09-30 21:36:432799 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232800
[email protected]1c773ea12009-04-28 19:58:422801 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232802 request.method = "GET";
2803 request.url = GURL("http://www.google.com/p/q/t");
2804 request.load_flags = 0;
2805
2806 MockWrite data_writes1[] = {
2807 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2808 "Host: www.google.com\r\n"
2809 "Connection: keep-alive\r\n\r\n"),
2810 };
2811
2812 MockRead data_reads1[] = {
2813 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2814 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2815 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422816 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232817 };
2818
2819 // Resend with authorization from cache for MyRealm.
2820 MockWrite data_writes2[] = {
2821 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2822 "Host: www.google.com\r\n"
2823 "Connection: keep-alive\r\n"
2824 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2825 };
2826
2827 // Sever rejects the authorization.
2828 MockRead data_reads2[] = {
2829 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2830 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2831 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422832 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232833 };
2834
2835 // At this point we should prompt for new credentials for MyRealm.
2836 // Restart with username=foo3, password=foo4.
2837 MockWrite data_writes3[] = {
2838 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2839 "Host: www.google.com\r\n"
2840 "Connection: keep-alive\r\n"
2841 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2842 };
2843
2844 // Sever accepts the authorization.
2845 MockRead data_reads3[] = {
2846 MockRead("HTTP/1.0 200 OK\r\n"),
2847 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422848 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232849 };
2850
[email protected]31a2bfe2010-02-09 08:03:392851 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2852 data_writes1, arraysize(data_writes1));
2853 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2854 data_writes2, arraysize(data_writes2));
2855 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2856 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592857 session_deps.socket_factory.AddSocketDataProvider(&data1);
2858 session_deps.socket_factory.AddSocketDataProvider(&data2);
2859 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232860
2861 TestCompletionCallback callback1;
2862
[email protected]684970b2009-08-14 04:54:462863 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422864 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232865
2866 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422867 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232868
[email protected]0757e7702009-03-27 04:00:222869 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2870 TestCompletionCallback callback2;
2871 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422872 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222873 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422874 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222875 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2876
[email protected]1c773ea12009-04-28 19:58:422877 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232878 EXPECT_FALSE(response == NULL);
2879
2880 // The password prompt info should have been set in
2881 // response->auth_challenge.
2882 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2883
[email protected]71e4573a2009-05-21 22:03:002884 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232885 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2886 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2887
[email protected]0757e7702009-03-27 04:00:222888 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232889
[email protected]0757e7702009-03-27 04:00:222890 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422891 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232892
[email protected]0757e7702009-03-27 04:00:222893 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422894 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232895
2896 response = trans->GetResponseInfo();
2897 EXPECT_FALSE(response == NULL);
2898 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2899 EXPECT_EQ(100, response->headers->GetContentLength());
2900 }
2901}
[email protected]89ceba9a2009-03-21 03:46:062902
2903// Test the ResetStateForRestart() private method.
2904TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2905 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592906 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402907 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432908 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062909
2910 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062911 trans->read_buf_ = new IOBuffer(15);
2912 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572913 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062914
2915 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:142916 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:572917 response->auth_challenge = new AuthChallengeInfo();
2918 response->ssl_info.cert_status = -15;
2919 response->response_time = base::Time::Now();
2920 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062921
2922 { // Setup state for response_.vary_data
2923 HttpRequestInfo request;
2924 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2925 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:572926 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:432927 request.extra_headers.SetHeader("Foo", "1");
2928 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:572929 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:062930 }
2931
2932 // Cause the above state to be reset.
2933 trans->ResetStateForRestart();
2934
2935 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:072936 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:062937 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:572938 EXPECT_EQ(0U, trans->request_headers_.size());
2939 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2940 EXPECT_TRUE(response->headers.get() == NULL);
2941 EXPECT_EQ(false, response->was_cached);
2942 EXPECT_EQ(0, response->ssl_info.cert_status);
2943 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:062944}
2945
[email protected]bacff652009-03-31 17:50:332946// Test HTTPS connections to a site with a bad certificate
2947TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592948 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402949 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432950 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332951
2952 HttpRequestInfo request;
2953 request.method = "GET";
2954 request.url = GURL("https://www.google.com/");
2955 request.load_flags = 0;
2956
2957 MockWrite data_writes[] = {
2958 MockWrite("GET / HTTP/1.1\r\n"
2959 "Host: www.google.com\r\n"
2960 "Connection: keep-alive\r\n\r\n"),
2961 };
2962
2963 MockRead data_reads[] = {
2964 MockRead("HTTP/1.0 200 OK\r\n"),
2965 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2966 MockRead("Content-Length: 100\r\n\r\n"),
2967 MockRead(false, OK),
2968 };
2969
[email protected]5ecc992a42009-11-11 01:41:592970 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:392971 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2972 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592973 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2974 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:332975
[email protected]5ecc992a42009-11-11 01:41:592976 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2977 session_deps.socket_factory.AddSocketDataProvider(&data);
2978 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2979 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:332980
2981 TestCompletionCallback callback;
2982
[email protected]684970b2009-08-14 04:54:462983 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332984 EXPECT_EQ(ERR_IO_PENDING, rv);
2985
2986 rv = callback.WaitForResult();
2987 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2988
2989 rv = trans->RestartIgnoringLastError(&callback);
2990 EXPECT_EQ(ERR_IO_PENDING, rv);
2991
2992 rv = callback.WaitForResult();
2993 EXPECT_EQ(OK, rv);
2994
2995 const HttpResponseInfo* response = trans->GetResponseInfo();
2996
2997 EXPECT_FALSE(response == NULL);
2998 EXPECT_EQ(100, response->headers->GetContentLength());
2999}
3000
3001// Test HTTPS connections to a site with a bad certificate, going through a
3002// proxy
3003TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593004 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333005
3006 HttpRequestInfo request;
3007 request.method = "GET";
3008 request.url = GURL("https://www.google.com/");
3009 request.load_flags = 0;
3010
3011 MockWrite proxy_writes[] = {
3012 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453013 "Host: www.google.com\r\n"
3014 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333015 };
3016
3017 MockRead proxy_reads[] = {
3018 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423019 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333020 };
3021
3022 MockWrite data_writes[] = {
3023 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453024 "Host: www.google.com\r\n"
3025 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333026 MockWrite("GET / HTTP/1.1\r\n"
3027 "Host: www.google.com\r\n"
3028 "Connection: keep-alive\r\n\r\n"),
3029 };
3030
3031 MockRead data_reads[] = {
3032 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3033 MockRead("HTTP/1.0 200 OK\r\n"),
3034 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3035 MockRead("Content-Length: 100\r\n\r\n"),
3036 MockRead(false, OK),
3037 };
3038
[email protected]31a2bfe2010-02-09 08:03:393039 StaticSocketDataProvider ssl_bad_certificate(
3040 proxy_reads, arraysize(proxy_reads),
3041 proxy_writes, arraysize(proxy_writes));
3042 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3043 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593044 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3045 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333046
[email protected]5ecc992a42009-11-11 01:41:593047 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3048 session_deps.socket_factory.AddSocketDataProvider(&data);
3049 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3050 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333051
3052 TestCompletionCallback callback;
3053
3054 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593055 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333056
[email protected]d207a5f2009-06-04 05:28:403057 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433058 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333059
[email protected]684970b2009-08-14 04:54:463060 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:333061 EXPECT_EQ(ERR_IO_PENDING, rv);
3062
3063 rv = callback.WaitForResult();
3064 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3065
3066 rv = trans->RestartIgnoringLastError(&callback);
3067 EXPECT_EQ(ERR_IO_PENDING, rv);
3068
3069 rv = callback.WaitForResult();
3070 EXPECT_EQ(OK, rv);
3071
3072 const HttpResponseInfo* response = trans->GetResponseInfo();
3073
3074 EXPECT_FALSE(response == NULL);
3075 EXPECT_EQ(100, response->headers->GetContentLength());
3076 }
3077}
3078
[email protected]1c773ea12009-04-28 19:58:423079TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593080 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403081 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433082 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423083
3084 HttpRequestInfo request;
3085 request.method = "GET";
3086 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433087 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3088 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423089
3090 MockWrite data_writes[] = {
3091 MockWrite("GET / HTTP/1.1\r\n"
3092 "Host: www.google.com\r\n"
3093 "Connection: keep-alive\r\n"
3094 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3095 };
3096
3097 // Lastly, the server responds with the actual content.
3098 MockRead data_reads[] = {
3099 MockRead("HTTP/1.0 200 OK\r\n"),
3100 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3101 MockRead("Content-Length: 100\r\n\r\n"),
3102 MockRead(false, OK),
3103 };
3104
[email protected]31a2bfe2010-02-09 08:03:393105 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3106 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593107 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423108
3109 TestCompletionCallback callback;
3110
[email protected]684970b2009-08-14 04:54:463111 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423112 EXPECT_EQ(ERR_IO_PENDING, rv);
3113
3114 rv = callback.WaitForResult();
3115 EXPECT_EQ(OK, rv);
3116}
3117
3118TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593119 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403120 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433121 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423122
3123 HttpRequestInfo request;
3124 request.method = "GET";
3125 request.url = GURL("http://www.google.com/");
3126 request.load_flags = 0;
3127 request.referrer = GURL("http://the.previous.site.com/");
3128
3129 MockWrite data_writes[] = {
3130 MockWrite("GET / HTTP/1.1\r\n"
3131 "Host: www.google.com\r\n"
3132 "Connection: keep-alive\r\n"
3133 "Referer: http://the.previous.site.com/\r\n\r\n"),
3134 };
3135
3136 // Lastly, the server responds with the actual content.
3137 MockRead data_reads[] = {
3138 MockRead("HTTP/1.0 200 OK\r\n"),
3139 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3140 MockRead("Content-Length: 100\r\n\r\n"),
3141 MockRead(false, OK),
3142 };
3143
[email protected]31a2bfe2010-02-09 08:03:393144 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3145 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593146 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423147
3148 TestCompletionCallback callback;
3149
[email protected]684970b2009-08-14 04:54:463150 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423151 EXPECT_EQ(ERR_IO_PENDING, rv);
3152
3153 rv = callback.WaitForResult();
3154 EXPECT_EQ(OK, rv);
3155}
3156
3157TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593158 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403159 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433160 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423161
3162 HttpRequestInfo request;
3163 request.method = "POST";
3164 request.url = GURL("http://www.google.com/");
3165
3166 MockWrite data_writes[] = {
3167 MockWrite("POST / HTTP/1.1\r\n"
3168 "Host: www.google.com\r\n"
3169 "Connection: keep-alive\r\n"
3170 "Content-Length: 0\r\n\r\n"),
3171 };
3172
3173 // Lastly, the server responds with the actual content.
3174 MockRead data_reads[] = {
3175 MockRead("HTTP/1.0 200 OK\r\n"),
3176 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3177 MockRead("Content-Length: 100\r\n\r\n"),
3178 MockRead(false, OK),
3179 };
3180
[email protected]31a2bfe2010-02-09 08:03:393181 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3182 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593183 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423184
3185 TestCompletionCallback callback;
3186
[email protected]684970b2009-08-14 04:54:463187 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423188 EXPECT_EQ(ERR_IO_PENDING, rv);
3189
3190 rv = callback.WaitForResult();
3191 EXPECT_EQ(OK, rv);
3192}
3193
3194TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593195 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403196 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433197 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423198
3199 HttpRequestInfo request;
3200 request.method = "PUT";
3201 request.url = GURL("http://www.google.com/");
3202
3203 MockWrite data_writes[] = {
3204 MockWrite("PUT / HTTP/1.1\r\n"
3205 "Host: www.google.com\r\n"
3206 "Connection: keep-alive\r\n"
3207 "Content-Length: 0\r\n\r\n"),
3208 };
3209
3210 // Lastly, the server responds with the actual content.
3211 MockRead data_reads[] = {
3212 MockRead("HTTP/1.0 200 OK\r\n"),
3213 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3214 MockRead("Content-Length: 100\r\n\r\n"),
3215 MockRead(false, OK),
3216 };
3217
[email protected]31a2bfe2010-02-09 08:03:393218 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3219 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593220 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423221
3222 TestCompletionCallback callback;
3223
[email protected]684970b2009-08-14 04:54:463224 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423225 EXPECT_EQ(ERR_IO_PENDING, rv);
3226
3227 rv = callback.WaitForResult();
3228 EXPECT_EQ(OK, rv);
3229}
3230
3231TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593232 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403233 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433234 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423235
3236 HttpRequestInfo request;
3237 request.method = "HEAD";
3238 request.url = GURL("http://www.google.com/");
3239
3240 MockWrite data_writes[] = {
3241 MockWrite("HEAD / HTTP/1.1\r\n"
3242 "Host: www.google.com\r\n"
3243 "Connection: keep-alive\r\n"
3244 "Content-Length: 0\r\n\r\n"),
3245 };
3246
3247 // Lastly, the server responds with the actual content.
3248 MockRead data_reads[] = {
3249 MockRead("HTTP/1.0 200 OK\r\n"),
3250 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3251 MockRead("Content-Length: 100\r\n\r\n"),
3252 MockRead(false, OK),
3253 };
3254
[email protected]31a2bfe2010-02-09 08:03:393255 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3256 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593257 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423258
3259 TestCompletionCallback callback;
3260
[email protected]684970b2009-08-14 04:54:463261 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423262 EXPECT_EQ(ERR_IO_PENDING, rv);
3263
3264 rv = callback.WaitForResult();
3265 EXPECT_EQ(OK, rv);
3266}
3267
3268TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593269 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403270 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433271 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423272
3273 HttpRequestInfo request;
3274 request.method = "GET";
3275 request.url = GURL("http://www.google.com/");
3276 request.load_flags = LOAD_BYPASS_CACHE;
3277
3278 MockWrite data_writes[] = {
3279 MockWrite("GET / HTTP/1.1\r\n"
3280 "Host: www.google.com\r\n"
3281 "Connection: keep-alive\r\n"
3282 "Pragma: no-cache\r\n"
3283 "Cache-Control: no-cache\r\n\r\n"),
3284 };
3285
3286 // Lastly, the server responds with the actual content.
3287 MockRead data_reads[] = {
3288 MockRead("HTTP/1.0 200 OK\r\n"),
3289 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3290 MockRead("Content-Length: 100\r\n\r\n"),
3291 MockRead(false, OK),
3292 };
3293
[email protected]31a2bfe2010-02-09 08:03:393294 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3295 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593296 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423297
3298 TestCompletionCallback callback;
3299
[email protected]684970b2009-08-14 04:54:463300 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423301 EXPECT_EQ(ERR_IO_PENDING, rv);
3302
3303 rv = callback.WaitForResult();
3304 EXPECT_EQ(OK, rv);
3305}
3306
3307TEST_F(HttpNetworkTransactionTest,
3308 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593309 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403310 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433311 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423312
3313 HttpRequestInfo request;
3314 request.method = "GET";
3315 request.url = GURL("http://www.google.com/");
3316 request.load_flags = LOAD_VALIDATE_CACHE;
3317
3318 MockWrite data_writes[] = {
3319 MockWrite("GET / HTTP/1.1\r\n"
3320 "Host: www.google.com\r\n"
3321 "Connection: keep-alive\r\n"
3322 "Cache-Control: max-age=0\r\n\r\n"),
3323 };
3324
3325 // Lastly, the server responds with the actual content.
3326 MockRead data_reads[] = {
3327 MockRead("HTTP/1.0 200 OK\r\n"),
3328 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3329 MockRead("Content-Length: 100\r\n\r\n"),
3330 MockRead(false, OK),
3331 };
3332
[email protected]31a2bfe2010-02-09 08:03:393333 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3334 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593335 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423336
3337 TestCompletionCallback callback;
3338
[email protected]684970b2009-08-14 04:54:463339 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423340 EXPECT_EQ(ERR_IO_PENDING, rv);
3341
3342 rv = callback.WaitForResult();
3343 EXPECT_EQ(OK, rv);
3344}
3345
3346TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593347 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403348 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433349 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423350
3351 HttpRequestInfo request;
3352 request.method = "GET";
3353 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433354 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423355
3356 MockWrite data_writes[] = {
3357 MockWrite("GET / HTTP/1.1\r\n"
3358 "Host: www.google.com\r\n"
3359 "Connection: keep-alive\r\n"
3360 "FooHeader: Bar\r\n\r\n"),
3361 };
3362
3363 // Lastly, the server responds with the actual content.
3364 MockRead data_reads[] = {
3365 MockRead("HTTP/1.0 200 OK\r\n"),
3366 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3367 MockRead("Content-Length: 100\r\n\r\n"),
3368 MockRead(false, OK),
3369 };
3370
[email protected]31a2bfe2010-02-09 08:03:393371 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3372 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593373 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423374
3375 TestCompletionCallback callback;
3376
[email protected]684970b2009-08-14 04:54:463377 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423378 EXPECT_EQ(ERR_IO_PENDING, rv);
3379
3380 rv = callback.WaitForResult();
3381 EXPECT_EQ(OK, rv);
3382}
3383
[email protected]270c6412010-03-29 22:02:473384TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3385 SessionDependencies session_deps;
3386 scoped_ptr<HttpTransaction> trans(
3387 new HttpNetworkTransaction(CreateSession(&session_deps)));
3388
3389 HttpRequestInfo request;
3390 request.method = "GET";
3391 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433392 request.extra_headers.SetHeader("referer", "www.foo.com");
3393 request.extra_headers.SetHeader("hEllo", "Kitty");
3394 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473395
3396 MockWrite data_writes[] = {
3397 MockWrite("GET / HTTP/1.1\r\n"
3398 "Host: www.google.com\r\n"
3399 "Connection: keep-alive\r\n"
3400 "hEllo: Kitty\r\n"
3401 "FoO: bar\r\n\r\n"),
3402 };
3403
3404 // Lastly, the server responds with the actual content.
3405 MockRead data_reads[] = {
3406 MockRead("HTTP/1.0 200 OK\r\n"),
3407 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3408 MockRead("Content-Length: 100\r\n\r\n"),
3409 MockRead(false, OK),
3410 };
3411
3412 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3413 data_writes, arraysize(data_writes));
3414 session_deps.socket_factory.AddSocketDataProvider(&data);
3415
3416 TestCompletionCallback callback;
3417
3418 int rv = trans->Start(&request, &callback, NULL);
3419 EXPECT_EQ(ERR_IO_PENDING, rv);
3420
3421 rv = callback.WaitForResult();
3422 EXPECT_EQ(OK, rv);
3423}
3424
[email protected]3cd17242009-06-23 02:59:023425TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093426 SessionDependencies session_deps(
3427 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023428
3429 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433430 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023431
3432 HttpRequestInfo request;
3433 request.method = "GET";
3434 request.url = GURL("http://www.google.com/");
3435 request.load_flags = 0;
3436
3437 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3438 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3439
3440 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353441 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023442 MockWrite("GET / HTTP/1.1\r\n"
3443 "Host: www.google.com\r\n"
3444 "Connection: keep-alive\r\n\r\n")
3445 };
3446
3447 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593448 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023449 MockRead("HTTP/1.0 200 OK\r\n"),
3450 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3451 MockRead("Payload"),
3452 MockRead(false, OK)
3453 };
3454
[email protected]31a2bfe2010-02-09 08:03:393455 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3456 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593457 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023458
3459 TestCompletionCallback callback;
3460
[email protected]684970b2009-08-14 04:54:463461 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023462 EXPECT_EQ(ERR_IO_PENDING, rv);
3463
3464 rv = callback.WaitForResult();
3465 EXPECT_EQ(OK, rv);
3466
3467 const HttpResponseInfo* response = trans->GetResponseInfo();
3468 EXPECT_FALSE(response == NULL);
3469
3470 std::string response_text;
3471 rv = ReadTransaction(trans.get(), &response_text);
3472 EXPECT_EQ(OK, rv);
3473 EXPECT_EQ("Payload", response_text);
3474}
3475
3476TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093477 SessionDependencies session_deps(
3478 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023479
3480 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433481 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023482
3483 HttpRequestInfo request;
3484 request.method = "GET";
3485 request.url = GURL("https://www.google.com/");
3486 request.load_flags = 0;
3487
3488 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3489 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3490
3491 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353492 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3493 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023494 MockWrite("GET / HTTP/1.1\r\n"
3495 "Host: www.google.com\r\n"
3496 "Connection: keep-alive\r\n\r\n")
3497 };
3498
3499 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353500 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3501 arraysize(read_buffer)),
3502 MockRead("HTTP/1.0 200 OK\r\n"),
3503 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3504 MockRead("Payload"),
3505 MockRead(false, OK)
3506 };
3507
[email protected]31a2bfe2010-02-09 08:03:393508 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3509 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593510 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353511
[email protected]5ecc992a42009-11-11 01:41:593512 SSLSocketDataProvider ssl(true, OK);
3513 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353514
3515 TestCompletionCallback callback;
3516
[email protected]684970b2009-08-14 04:54:463517 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353518 EXPECT_EQ(ERR_IO_PENDING, rv);
3519
3520 rv = callback.WaitForResult();
3521 EXPECT_EQ(OK, rv);
3522
3523 const HttpResponseInfo* response = trans->GetResponseInfo();
3524 EXPECT_FALSE(response == NULL);
3525
3526 std::string response_text;
3527 rv = ReadTransaction(trans.get(), &response_text);
3528 EXPECT_EQ(OK, rv);
3529 EXPECT_EQ("Payload", response_text);
3530}
3531
3532TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093533 SessionDependencies session_deps(
3534 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353535
3536 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433537 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353538
3539 HttpRequestInfo request;
3540 request.method = "GET";
3541 request.url = GURL("http://www.google.com/");
3542 request.load_flags = 0;
3543
3544 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3545 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373546 const char kSOCKS5OkRequest[] = {
3547 0x05, // Version
3548 0x01, // Command (CONNECT)
3549 0x00, // Reserved.
3550 0x03, // Address type (DOMAINNAME).
3551 0x0E, // Length of domain (14)
3552 // Domain string:
3553 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3554 0x00, 0x50, // 16-bit port (80)
3555 };
[email protected]e0c27be2009-07-15 13:09:353556 const char kSOCKS5OkResponse[] =
3557 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3558
3559 MockWrite data_writes[] = {
3560 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3561 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3562 MockWrite("GET / HTTP/1.1\r\n"
3563 "Host: www.google.com\r\n"
3564 "Connection: keep-alive\r\n\r\n")
3565 };
3566
3567 MockRead data_reads[] = {
3568 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3569 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3570 MockRead("HTTP/1.0 200 OK\r\n"),
3571 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3572 MockRead("Payload"),
3573 MockRead(false, OK)
3574 };
3575
[email protected]31a2bfe2010-02-09 08:03:393576 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3577 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593578 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353579
3580 TestCompletionCallback callback;
3581
[email protected]684970b2009-08-14 04:54:463582 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353583 EXPECT_EQ(ERR_IO_PENDING, rv);
3584
3585 rv = callback.WaitForResult();
3586 EXPECT_EQ(OK, rv);
3587
3588 const HttpResponseInfo* response = trans->GetResponseInfo();
3589 EXPECT_FALSE(response == NULL);
3590
3591 std::string response_text;
3592 rv = ReadTransaction(trans.get(), &response_text);
3593 EXPECT_EQ(OK, rv);
3594 EXPECT_EQ("Payload", response_text);
3595}
3596
3597TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093598 SessionDependencies session_deps(
3599 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353600
3601 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433602 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353603
3604 HttpRequestInfo request;
3605 request.method = "GET";
3606 request.url = GURL("https://www.google.com/");
3607 request.load_flags = 0;
3608
3609 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3610 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373611 const unsigned char kSOCKS5OkRequest[] = {
3612 0x05, // Version
3613 0x01, // Command (CONNECT)
3614 0x00, // Reserved.
3615 0x03, // Address type (DOMAINNAME).
3616 0x0E, // Length of domain (14)
3617 // Domain string:
3618 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3619 0x01, 0xBB, // 16-bit port (443)
3620 };
3621
[email protected]e0c27be2009-07-15 13:09:353622 const char kSOCKS5OkResponse[] =
3623 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3624
3625 MockWrite data_writes[] = {
3626 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3627 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3628 arraysize(kSOCKS5OkRequest)),
3629 MockWrite("GET / HTTP/1.1\r\n"
3630 "Host: www.google.com\r\n"
3631 "Connection: keep-alive\r\n\r\n")
3632 };
3633
3634 MockRead data_reads[] = {
3635 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3636 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023637 MockRead("HTTP/1.0 200 OK\r\n"),
3638 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3639 MockRead("Payload"),
3640 MockRead(false, OK)
3641 };
3642
[email protected]31a2bfe2010-02-09 08:03:393643 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3644 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593645 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023646
[email protected]5ecc992a42009-11-11 01:41:593647 SSLSocketDataProvider ssl(true, OK);
3648 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023649
3650 TestCompletionCallback callback;
3651
[email protected]684970b2009-08-14 04:54:463652 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023653 EXPECT_EQ(ERR_IO_PENDING, rv);
3654
3655 rv = callback.WaitForResult();
3656 EXPECT_EQ(OK, rv);
3657
3658 const HttpResponseInfo* response = trans->GetResponseInfo();
3659 EXPECT_FALSE(response == NULL);
3660
3661 std::string response_text;
3662 rv = ReadTransaction(trans.get(), &response_text);
3663 EXPECT_EQ(OK, rv);
3664 EXPECT_EQ("Payload", response_text);
3665}
3666
[email protected]04e5be32009-06-26 20:00:313667// Tests that for connection endpoints the group names are correctly set.
3668TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3669 const struct {
3670 const std::string proxy_server;
3671 const std::string url;
3672 const std::string expected_group_name;
3673 } tests[] = {
3674 {
3675 "", // no proxy (direct)
3676 "http://www.google.com/direct",
3677 "http://www.google.com/",
3678 },
3679 {
3680 "http_proxy",
3681 "http://www.google.com/http_proxy_normal",
3682 "proxy/http_proxy:80/",
3683 },
3684 {
3685 "socks4://socks_proxy:1080",
3686 "http://www.google.com/socks4_direct",
3687 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3688 },
3689
3690 // SSL Tests
3691 {
3692 "",
3693 "https://www.google.com/direct_ssl",
3694 "https://www.google.com/",
3695 },
3696 {
3697 "http_proxy",
3698 "https://www.google.com/http_connect_ssl",
3699 "proxy/http_proxy:80/https://www.google.com/",
3700 },
3701 {
3702 "socks4://socks_proxy:1080",
3703 "https://www.google.com/socks4_ssl",
3704 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3705 },
3706 };
3707
3708 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093709 SessionDependencies session_deps(
3710 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313711
[email protected]04e5be32009-06-26 20:00:313712 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a796bcec2010-03-22 17:17:263713
3714 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
3715 new CaptureGroupNameTCPSocketPool(session.get(),
3716 session->socket_factory()));
3717 session->tcp_socket_pool_ = tcp_conn_pool.get();
3718 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
3719 new CaptureGroupNameSOCKSSocketPool(session.get(),
3720 tcp_conn_pool.get()));
3721 session->socks_socket_pool_ = socks_conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313722
[email protected]5695b8c2009-09-30 21:36:433723 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313724
3725 HttpRequestInfo request;
3726 request.method = "GET";
3727 request.url = GURL(tests[i].url);
3728 request.load_flags = 0;
3729
3730 TestCompletionCallback callback;
3731
3732 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463733 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]a796bcec2010-03-22 17:17:263734 std::string allgroups = tcp_conn_pool->last_group_name_received() +
3735 socks_conn_pool->last_group_name_received();
3736 EXPECT_EQ(tests[i].expected_group_name, allgroups);
[email protected]04e5be32009-06-26 20:00:313737 }
3738}
3739
[email protected]9172a982009-06-06 00:30:253740TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543741 SessionDependencies session_deps(
3742 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323743
[email protected]69719062010-01-05 20:09:213744 // This simulates failure resolving all hostnames; that means we will fail
3745 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:323746 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3747
[email protected]9172a982009-06-06 00:30:253748 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433749 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253750
3751 HttpRequestInfo request;
3752 request.method = "GET";
3753 request.url = GURL("http://www.google.com/");
3754
3755 TestCompletionCallback callback;
3756
[email protected]684970b2009-08-14 04:54:463757 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253758 EXPECT_EQ(ERR_IO_PENDING, rv);
3759
[email protected]9172a982009-06-06 00:30:253760 rv = callback.WaitForResult();
3761 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3762}
3763
[email protected]f3e6c1e2009-06-15 20:52:123764// Host resolution observer used by
3765// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3766// resovle requests are issued with a referrer of |expected_referrer|.
3767class ResolutionReferrerObserver : public HostResolver::Observer {
3768 public:
3769 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3770 : expected_referrer_(expected_referrer),
3771 called_start_with_referrer_(false),
3772 called_finish_with_referrer_(false) {
3773 }
3774
3775 virtual void OnStartResolution(int id,
3776 const HostResolver::RequestInfo& info) {
3777 if (info.referrer() == expected_referrer_)
3778 called_start_with_referrer_ = true;
3779 }
3780
3781 virtual void OnFinishResolutionWithStatus(
3782 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3783 if (info.referrer() == expected_referrer_)
3784 called_finish_with_referrer_ = true;
3785 }
3786
[email protected]eb255d32009-06-17 02:11:033787 virtual void OnCancelResolution(int id,
3788 const HostResolver::RequestInfo& info ) {
3789 FAIL() << "Should not be cancelling any requests!";
3790 }
3791
[email protected]f3e6c1e2009-06-15 20:52:123792 bool did_complete_with_expected_referrer() const {
3793 return called_start_with_referrer_ && called_finish_with_referrer_;
3794 }
3795
3796 private:
3797 GURL expected_referrer_;
3798 bool called_start_with_referrer_;
3799 bool called_finish_with_referrer_;
3800
3801 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3802};
3803
3804// Make sure that when HostResolver::Resolve() is invoked, it passes through
3805// the "referrer". This is depended on by the DNS prefetch observer.
3806TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3807 GURL referrer = GURL("http://expected-referrer/");
3808 EXPECT_TRUE(referrer.is_valid());
3809 ResolutionReferrerObserver resolution_observer(referrer);
3810
3811 SessionDependencies session_deps;
3812 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433813 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123814
3815 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143816 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123817
3818 // Connect up a mock socket which will fail when reading.
3819 MockRead data_reads[] = {
3820 MockRead(false, ERR_FAILED),
3821 };
[email protected]31a2bfe2010-02-09 08:03:393822 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593823 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:123824
3825 // Issue a request, containing an HTTP referrer.
3826 HttpRequestInfo request;
3827 request.method = "GET";
3828 request.referrer = referrer;
3829 request.url = GURL("http://www.google.com/");
3830
3831 // Run the request until it fails reading from the socket.
3832 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463833 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123834 EXPECT_EQ(ERR_IO_PENDING, rv);
3835 rv = callback.WaitForResult();
3836 EXPECT_EQ(ERR_FAILED, rv);
3837
3838 // Check that the host resolution observer saw |referrer|.
3839 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3840}
3841
[email protected]3b9cca42009-06-16 01:08:283842// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3843// host cache is bypassed.
3844TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3845 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323846
[email protected]a2c2fb92009-07-18 07:31:043847 // Select a host resolver that does caching.
3848 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323849
[email protected]3b9cca42009-06-16 01:08:283850 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433851 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:283852
3853 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3854 // a synchronous lookup.)
3855 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143856 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463857 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3858 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283859 EXPECT_EQ(OK, rv);
3860
3861 // Verify that it was added to host cache, by doing a subsequent async lookup
3862 // and confirming it completes synchronously.
3863 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463864 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283865 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463866 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323867 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283868
3869 // Inject a failure the next time that "www.google.com" is resolved. This way
3870 // we can tell if the next lookup hit the cache, or the "network".
3871 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323872 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283873
3874 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3875 // first read -- this won't be reached as the host resolution will fail first.
3876 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:393877 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593878 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:283879
3880 // Issue a request, asking to bypass the cache(s).
3881 HttpRequestInfo request;
3882 request.method = "GET";
3883 request.load_flags = LOAD_BYPASS_CACHE;
3884 request.url = GURL("http://www.google.com/");
3885
3886 // Run the request.
3887 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463888 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283889 ASSERT_EQ(ERR_IO_PENDING, rv);
3890 rv = callback.WaitForResult();
3891
3892 // If we bypassed the cache, we would have gotten a failure while resolving
3893 // "www.google.com".
3894 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3895}
3896
[email protected]0877e3d2009-10-17 22:29:573897// Make sure we can handle an error when writing the request.
3898TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3899 SessionDependencies session_deps;
3900 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3901
3902 HttpRequestInfo request;
3903 request.method = "GET";
3904 request.url = GURL("http://www.foo.com/");
3905 request.load_flags = 0;
3906
3907 MockWrite write_failure[] = {
3908 MockWrite(true, ERR_CONNECTION_RESET),
3909 };
[email protected]31a2bfe2010-02-09 08:03:393910 StaticSocketDataProvider data(NULL, 0,
3911 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:593912 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573913
3914 TestCompletionCallback callback;
3915
3916 scoped_ptr<HttpTransaction> trans(
3917 new HttpNetworkTransaction(CreateSession(&session_deps)));
3918
3919 int rv = trans->Start(&request, &callback, NULL);
3920 EXPECT_EQ(ERR_IO_PENDING, rv);
3921
3922 rv = callback.WaitForResult();
3923 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3924}
3925
3926// Check that a connection closed after the start of the headers finishes ok.
3927TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3928 SessionDependencies session_deps;
3929 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3930
3931 HttpRequestInfo request;
3932 request.method = "GET";
3933 request.url = GURL("http://www.foo.com/");
3934 request.load_flags = 0;
3935
3936 MockRead data_reads[] = {
3937 MockRead("HTTP/1."),
3938 MockRead(false, OK),
3939 };
3940
[email protected]31a2bfe2010-02-09 08:03:393941 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593942 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573943
3944 TestCompletionCallback callback;
3945
3946 scoped_ptr<HttpTransaction> trans(
3947 new HttpNetworkTransaction(CreateSession(&session_deps)));
3948
3949 int rv = trans->Start(&request, &callback, NULL);
3950 EXPECT_EQ(ERR_IO_PENDING, rv);
3951
3952 rv = callback.WaitForResult();
3953 EXPECT_EQ(OK, rv);
3954
3955 const HttpResponseInfo* response = trans->GetResponseInfo();
3956 EXPECT_TRUE(response != NULL);
3957
3958 EXPECT_TRUE(response->headers != NULL);
3959 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
3960
3961 std::string response_data;
3962 rv = ReadTransaction(trans.get(), &response_data);
3963 EXPECT_EQ(OK, rv);
3964 EXPECT_EQ("", response_data);
3965}
3966
3967// Make sure that a dropped connection while draining the body for auth
3968// restart does the right thing.
3969TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
3970 SessionDependencies session_deps;
3971 scoped_ptr<HttpTransaction> trans(
3972 new HttpNetworkTransaction(CreateSession(&session_deps)));
3973
3974 HttpRequestInfo request;
3975 request.method = "GET";
3976 request.url = GURL("http://www.google.com/");
3977 request.load_flags = 0;
3978
3979 MockWrite data_writes1[] = {
3980 MockWrite("GET / HTTP/1.1\r\n"
3981 "Host: www.google.com\r\n"
3982 "Connection: keep-alive\r\n\r\n"),
3983 };
3984
3985 MockRead data_reads1[] = {
3986 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3987 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3988 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3989 MockRead("Content-Length: 14\r\n\r\n"),
3990 MockRead("Unauth"),
3991 MockRead(true, ERR_CONNECTION_RESET),
3992 };
3993
[email protected]31a2bfe2010-02-09 08:03:393994 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3995 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593996 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:573997
3998 // After calling trans->RestartWithAuth(), this is the request we should
3999 // be issuing -- the final header line contains the credentials.
4000 MockWrite data_writes2[] = {
4001 MockWrite("GET / HTTP/1.1\r\n"
4002 "Host: www.google.com\r\n"
4003 "Connection: keep-alive\r\n"
4004 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4005 };
4006
4007 // Lastly, the server responds with the actual content.
4008 MockRead data_reads2[] = {
4009 MockRead("HTTP/1.1 200 OK\r\n"),
4010 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4011 MockRead("Content-Length: 100\r\n\r\n"),
4012 MockRead(false, OK),
4013 };
4014
[email protected]31a2bfe2010-02-09 08:03:394015 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4016 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594017 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574018
4019 TestCompletionCallback callback1;
4020
4021 int rv = trans->Start(&request, &callback1, NULL);
4022 EXPECT_EQ(ERR_IO_PENDING, rv);
4023
4024 rv = callback1.WaitForResult();
4025 EXPECT_EQ(OK, rv);
4026
4027 const HttpResponseInfo* response = trans->GetResponseInfo();
4028 EXPECT_FALSE(response == NULL);
4029
4030 // The password prompt info should have been set in response->auth_challenge.
4031 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4032
4033 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4034 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4035 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4036
4037 TestCompletionCallback callback2;
4038
4039 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4040 EXPECT_EQ(ERR_IO_PENDING, rv);
4041
4042 rv = callback2.WaitForResult();
4043 EXPECT_EQ(OK, rv);
4044
4045 response = trans->GetResponseInfo();
4046 EXPECT_FALSE(response == NULL);
4047 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4048 EXPECT_EQ(100, response->headers->GetContentLength());
4049}
4050
4051// Test HTTPS connections going through a proxy that sends extra data.
4052TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4053 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4054
4055 HttpRequestInfo request;
4056 request.method = "GET";
4057 request.url = GURL("https://www.google.com/");
4058 request.load_flags = 0;
4059
4060 MockRead proxy_reads[] = {
4061 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4062 MockRead(false, OK)
4063 };
4064
[email protected]31a2bfe2010-02-09 08:03:394065 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594066 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574067
[email protected]5ecc992a42009-11-11 01:41:594068 session_deps.socket_factory.AddSocketDataProvider(&data);
4069 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574070
4071 TestCompletionCallback callback;
4072
4073 session_deps.socket_factory.ResetNextMockIndexes();
4074
4075 scoped_ptr<HttpTransaction> trans(
4076 new HttpNetworkTransaction(CreateSession(&session_deps)));
4077
4078 int rv = trans->Start(&request, &callback, NULL);
4079 EXPECT_EQ(ERR_IO_PENDING, rv);
4080
4081 rv = callback.WaitForResult();
4082 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4083}
4084
[email protected]e22e1362009-11-23 21:31:124085TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464086 SessionDependencies session_deps;
4087 scoped_ptr<HttpTransaction> trans(
4088 new HttpNetworkTransaction(CreateSession(&session_deps)));
4089
4090 HttpRequestInfo request;
4091 request.method = "GET";
4092 request.url = GURL("http://www.google.com/");
4093 request.load_flags = 0;
4094
[email protected]e22e1362009-11-23 21:31:124095 MockRead data_reads[] = {
4096 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4097 MockRead(false, OK),
4098 };
[email protected]9492e4a2010-02-24 00:58:464099
4100 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4101 session_deps.socket_factory.AddSocketDataProvider(&data);
4102
4103 TestCompletionCallback callback;
4104
4105 int rv = trans->Start(&request, &callback, NULL);
4106 EXPECT_EQ(ERR_IO_PENDING, rv);
4107
4108 EXPECT_EQ(OK, callback.WaitForResult());
4109
4110 const HttpResponseInfo* response = trans->GetResponseInfo();
4111 EXPECT_TRUE(response != NULL);
4112
4113 EXPECT_TRUE(response->headers != NULL);
4114 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4115
4116 std::string response_data;
4117 rv = ReadTransaction(trans.get(), &response_data);
4118 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124119}
4120
[email protected]95d88ffe2010-02-04 21:25:334121TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4122 SessionDependencies session_deps;
4123 scoped_ptr<HttpTransaction> trans(
4124 new HttpNetworkTransaction(CreateSession(&session_deps)));
4125
4126 HttpRequestInfo request;
4127 request.method = "POST";
4128 request.url = GURL("http://www.google.com/upload");
4129 request.upload_data = new UploadData;
4130 request.load_flags = 0;
4131
4132 FilePath temp_file_path;
4133 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4134 const uint64 kFakeSize = 100000; // file is actually blank
4135
4136 std::vector<UploadData::Element> elements;
4137 UploadData::Element element;
4138 element.SetToFilePath(temp_file_path);
4139 element.SetContentLength(kFakeSize);
4140 elements.push_back(element);
4141 request.upload_data->set_elements(elements);
4142 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4143
4144 MockRead data_reads[] = {
4145 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4146 MockRead("hello world"),
4147 MockRead(false, OK),
4148 };
[email protected]31a2bfe2010-02-09 08:03:394149 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334150 session_deps.socket_factory.AddSocketDataProvider(&data);
4151
4152 TestCompletionCallback callback;
4153
4154 int rv = trans->Start(&request, &callback, NULL);
4155 EXPECT_EQ(ERR_IO_PENDING, rv);
4156
4157 rv = callback.WaitForResult();
4158 EXPECT_EQ(OK, rv);
4159
4160 const HttpResponseInfo* response = trans->GetResponseInfo();
4161 EXPECT_TRUE(response != NULL);
4162
4163 EXPECT_TRUE(response->headers != NULL);
4164 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4165
4166 std::string response_data;
4167 rv = ReadTransaction(trans.get(), &response_data);
4168 EXPECT_EQ(OK, rv);
4169 EXPECT_EQ("hello world", response_data);
4170
4171 file_util::Delete(temp_file_path, false);
4172}
4173
[email protected]6624b4622010-03-29 19:58:364174TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4175 // If we try to upload an unreadable file, the network stack should report
4176 // the file size as zero and upload zero bytes for that file.
4177 SessionDependencies session_deps;
4178 scoped_ptr<HttpTransaction> trans(
4179 new HttpNetworkTransaction(CreateSession(&session_deps)));
4180
4181 FilePath temp_file;
4182 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4183 std::string temp_file_content("Unreadable file.");
4184 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4185 temp_file_content.length()));
4186 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4187
4188 HttpRequestInfo request;
4189 request.method = "POST";
4190 request.url = GURL("http://www.google.com/upload");
4191 request.upload_data = new UploadData;
4192 request.load_flags = 0;
4193
4194 std::vector<UploadData::Element> elements;
4195 UploadData::Element element;
4196 element.SetToFilePath(temp_file);
4197 elements.push_back(element);
4198 request.upload_data->set_elements(elements);
4199
4200 MockRead data_reads[] = {
4201 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4202 MockRead(false, OK),
4203 };
4204 MockWrite data_writes[] = {
4205 MockWrite("POST /upload HTTP/1.1\r\n"
4206 "Host: www.google.com\r\n"
4207 "Connection: keep-alive\r\n"
4208 "Content-Length: 0\r\n\r\n"),
4209 MockWrite(false, OK),
4210 };
4211 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4212 arraysize(data_writes));
4213 session_deps.socket_factory.AddSocketDataProvider(&data);
4214
4215 TestCompletionCallback callback;
4216
4217 int rv = trans->Start(&request, &callback, NULL);
4218 EXPECT_EQ(ERR_IO_PENDING, rv);
4219
4220 rv = callback.WaitForResult();
4221 EXPECT_EQ(OK, rv);
4222
4223 const HttpResponseInfo* response = trans->GetResponseInfo();
4224 EXPECT_TRUE(response != NULL);
4225 EXPECT_TRUE(response->headers != NULL);
4226 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4227
4228 file_util::Delete(temp_file, false);
4229}
4230
4231TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4232 SessionDependencies session_deps;
4233 scoped_ptr<HttpTransaction> trans(
4234 new HttpNetworkTransaction(CreateSession(&session_deps)));
4235
4236 FilePath temp_file;
4237 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4238 std::string temp_file_contents("Unreadable file.");
4239 std::string unreadable_contents(temp_file_contents.length(), '\0');
4240 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4241 temp_file_contents.length()));
4242
4243 HttpRequestInfo request;
4244 request.method = "POST";
4245 request.url = GURL("http://www.google.com/upload");
4246 request.upload_data = new UploadData;
4247 request.load_flags = 0;
4248
4249 std::vector<UploadData::Element> elements;
4250 UploadData::Element element;
4251 element.SetToFilePath(temp_file);
4252 elements.push_back(element);
4253 request.upload_data->set_elements(elements);
4254
4255 MockRead data_reads[] = {
4256 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4257 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4258 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4259
4260 MockRead("HTTP/1.1 200 OK\r\n"),
4261 MockRead("Content-Length: 0\r\n\r\n"),
4262 MockRead(false, OK),
4263 };
4264 MockWrite data_writes[] = {
4265 MockWrite("POST /upload HTTP/1.1\r\n"
4266 "Host: www.google.com\r\n"
4267 "Connection: keep-alive\r\n"
4268 "Content-Length: 16\r\n\r\n"),
4269 MockWrite(false, temp_file_contents.c_str()),
4270
4271 MockWrite("POST /upload HTTP/1.1\r\n"
4272 "Host: www.google.com\r\n"
4273 "Connection: keep-alive\r\n"
4274 "Content-Length: 16\r\n"
4275 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4276 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4277 MockWrite(false, OK),
4278 };
4279 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4280 arraysize(data_writes));
4281 session_deps.socket_factory.AddSocketDataProvider(&data);
4282
4283 TestCompletionCallback callback1;
4284
4285 int rv = trans->Start(&request, &callback1, NULL);
4286 EXPECT_EQ(ERR_IO_PENDING, rv);
4287
4288 rv = callback1.WaitForResult();
4289 EXPECT_EQ(OK, rv);
4290
4291 const HttpResponseInfo* response = trans->GetResponseInfo();
4292 EXPECT_TRUE(response != NULL);
4293 EXPECT_TRUE(response->headers != NULL);
4294 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4295
4296 // The password prompt info should have been set in response->auth_challenge.
4297 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4298 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4299 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4300 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4301
4302 // Now make the file unreadable and try again.
4303 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4304
4305 TestCompletionCallback callback2;
4306
4307 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4308 EXPECT_EQ(ERR_IO_PENDING, rv);
4309
4310 rv = callback2.WaitForResult();
4311 EXPECT_EQ(OK, rv);
4312
4313 response = trans->GetResponseInfo();
4314 EXPECT_TRUE(response != NULL);
4315 EXPECT_TRUE(response->headers != NULL);
4316 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4317 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4318
4319 file_util::Delete(temp_file, false);
4320}
4321
[email protected]aeefc9e82010-02-19 16:18:274322// Tests that changes to Auth realms are treated like auth rejections.
4323TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4324 SessionDependencies session_deps;
4325 scoped_ptr<HttpTransaction> trans(
4326 new HttpNetworkTransaction(CreateSession(&session_deps)));
4327
4328 HttpRequestInfo request;
4329 request.method = "GET";
4330 request.url = GURL("http://www.google.com/");
4331 request.load_flags = 0;
4332
4333 // First transaction will request a resource and receive a Basic challenge
4334 // with realm="first_realm".
4335 MockWrite data_writes1[] = {
4336 MockWrite("GET / HTTP/1.1\r\n"
4337 "Host: www.google.com\r\n"
4338 "Connection: keep-alive\r\n"
4339 "\r\n"),
4340 };
4341 MockRead data_reads1[] = {
4342 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4343 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4344 "\r\n"),
4345 };
4346
4347 // After calling trans->RestartWithAuth(), provide an Authentication header
4348 // for first_realm. The server will reject and provide a challenge with
4349 // second_realm.
4350 MockWrite data_writes2[] = {
4351 MockWrite("GET / HTTP/1.1\r\n"
4352 "Host: www.google.com\r\n"
4353 "Connection: keep-alive\r\n"
4354 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4355 "\r\n"),
4356 };
4357 MockRead data_reads2[] = {
4358 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4359 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4360 "\r\n"),
4361 };
4362
4363 // This again fails, and goes back to first_realm. Make sure that the
4364 // entry is removed from cache.
4365 MockWrite data_writes3[] = {
4366 MockWrite("GET / HTTP/1.1\r\n"
4367 "Host: www.google.com\r\n"
4368 "Connection: keep-alive\r\n"
4369 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4370 "\r\n"),
4371 };
4372 MockRead data_reads3[] = {
4373 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4374 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4375 "\r\n"),
4376 };
4377
4378 // Try one last time (with the correct password) and get the resource.
4379 MockWrite data_writes4[] = {
4380 MockWrite("GET / HTTP/1.1\r\n"
4381 "Host: www.google.com\r\n"
4382 "Connection: keep-alive\r\n"
4383 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4384 "\r\n"),
4385 };
4386 MockRead data_reads4[] = {
4387 MockRead("HTTP/1.1 200 OK\r\n"
4388 "Content-Type: text/html; charset=iso-8859-1\r\n"
4389 "Content-Length: 100\r\n"
4390 "\r\n"),
4391 };
4392
4393 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4394 data_writes1, arraysize(data_writes1));
4395 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4396 data_writes2, arraysize(data_writes2));
4397 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4398 data_writes3, arraysize(data_writes3));
4399 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4400 data_writes4, arraysize(data_writes4));
4401 session_deps.socket_factory.AddSocketDataProvider(&data1);
4402 session_deps.socket_factory.AddSocketDataProvider(&data2);
4403 session_deps.socket_factory.AddSocketDataProvider(&data3);
4404 session_deps.socket_factory.AddSocketDataProvider(&data4);
4405
4406 TestCompletionCallback callback1;
4407
4408 // Issue the first request with Authorize headers. There should be a
4409 // password prompt for first_realm waiting to be filled in after the
4410 // transaction completes.
4411 int rv = trans->Start(&request, &callback1, NULL);
4412 EXPECT_EQ(ERR_IO_PENDING, rv);
4413 rv = callback1.WaitForResult();
4414 EXPECT_EQ(OK, rv);
4415 const HttpResponseInfo* response = trans->GetResponseInfo();
4416 ASSERT_FALSE(response == NULL);
4417 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4418 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4419 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4420 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4421
4422 // Issue the second request with an incorrect password. There should be a
4423 // password prompt for second_realm waiting to be filled in after the
4424 // transaction completes.
4425 TestCompletionCallback callback2;
4426 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4427 EXPECT_EQ(ERR_IO_PENDING, rv);
4428 rv = callback2.WaitForResult();
4429 EXPECT_EQ(OK, rv);
4430 response = trans->GetResponseInfo();
4431 ASSERT_FALSE(response == NULL);
4432 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4433 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4434 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4435 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4436
4437 // Issue the third request with another incorrect password. There should be
4438 // a password prompt for first_realm waiting to be filled in. If the password
4439 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4440 // first_realm was not correctly removed.
4441 TestCompletionCallback callback3;
4442 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4443 EXPECT_EQ(ERR_IO_PENDING, rv);
4444 rv = callback3.WaitForResult();
4445 EXPECT_EQ(OK, rv);
4446 response = trans->GetResponseInfo();
4447 ASSERT_FALSE(response == NULL);
4448 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4449 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4450 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4451 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4452
4453 // Issue the fourth request with the correct password and username.
4454 TestCompletionCallback callback4;
4455 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4456 EXPECT_EQ(ERR_IO_PENDING, rv);
4457 rv = callback4.WaitForResult();
4458 EXPECT_EQ(OK, rv);
4459 response = trans->GetResponseInfo();
4460 ASSERT_FALSE(response == NULL);
4461 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4462}
4463
[email protected]564b4912010-03-09 16:30:424464TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424465 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:064466 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:424467
[email protected]564b4912010-03-09 16:30:424468 SessionDependencies session_deps;
4469
4470 MockRead data_reads[] = {
4471 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]31e2c69e2010-04-15 18:06:064472 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424473 MockRead("hello world"),
4474 MockRead(false, OK),
4475 };
4476
4477 HttpRequestInfo request;
4478 request.method = "GET";
4479 request.url = GURL("http://www.google.com/");
4480 request.load_flags = 0;
4481
4482 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4483
4484 session_deps.socket_factory.AddSocketDataProvider(&data);
4485
4486 TestCompletionCallback callback;
4487
4488 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4489 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4490
4491 int rv = trans->Start(&request, &callback, NULL);
4492 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534493
[email protected]564b4912010-03-09 16:30:424494 HostPortPair http_host_port_pair;
4495 http_host_port_pair.host = "www.google.com";
4496 http_host_port_pair.port = 80;
4497 const HttpAlternateProtocols& alternate_protocols =
4498 session->alternate_protocols();
4499 EXPECT_FALSE(
4500 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4501
4502 EXPECT_EQ(OK, callback.WaitForResult());
4503
4504 const HttpResponseInfo* response = trans->GetResponseInfo();
4505 ASSERT_TRUE(response != NULL);
4506 ASSERT_TRUE(response->headers != NULL);
4507 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4508
4509 std::string response_data;
4510 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4511 EXPECT_EQ("hello world", response_data);
4512
4513 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4514 const HttpAlternateProtocols::PortProtocolPair alternate =
4515 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4516 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4517 expected_alternate.port = 443;
[email protected]31e2c69e2010-04-15 18:06:064518 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_1;
[email protected]564b4912010-03-09 16:30:424519 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424520
[email protected]31e2c69e2010-04-15 18:06:064521 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:424522 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424523}
4524
4525TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:064526 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:424527 SessionDependencies session_deps;
4528
4529 HttpRequestInfo request;
4530 request.method = "GET";
4531 request.url = GURL("http://www.google.com/");
4532 request.load_flags = 0;
4533
4534 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4535 StaticSocketDataProvider first_data;
4536 first_data.set_connect_data(mock_connect);
4537 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4538
4539 MockRead data_reads[] = {
4540 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4541 MockRead("hello world"),
4542 MockRead(true, OK),
4543 };
4544 StaticSocketDataProvider second_data(
4545 data_reads, arraysize(data_reads), NULL, 0);
4546 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4547
4548 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4549 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4550 // http://crbug.com/37454.
4551 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4552
4553 TestCompletionCallback callback;
4554
4555 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4556
4557 HostPortPair http_host_port_pair;
4558 http_host_port_pair.host = "www.google.com";
4559 http_host_port_pair.port = 80;
4560 HttpAlternateProtocols* alternate_protocols =
4561 session->mutable_alternate_protocols();
4562 alternate_protocols->SetAlternateProtocolFor(
4563 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]31e2c69e2010-04-15 18:06:064564 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424565
4566 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4567
4568 int rv = trans->Start(&request, &callback, NULL);
4569 EXPECT_EQ(ERR_IO_PENDING, rv);
4570 EXPECT_EQ(OK, callback.WaitForResult());
4571
4572 const HttpResponseInfo* response = trans->GetResponseInfo();
4573 ASSERT_TRUE(response != NULL);
4574 ASSERT_TRUE(response->headers != NULL);
4575 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4576
4577 std::string response_data;
4578 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4579 EXPECT_EQ("hello world", response_data);
4580
4581 ASSERT_TRUE(
4582 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
4583 const HttpAlternateProtocols::PortProtocolPair alternate =
4584 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
4585 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:064586 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:424587}
4588
4589// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
4590// says that it does SPDY, but it just does the TLS handshake, but the NPN
4591// response does not indicate SPDY, so we just do standard HTTPS over the port.
4592// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
4593// on the original port.
[email protected]a2cb8122010-03-10 17:22:424594// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
4595// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:534596//
[email protected]a2cb8122010-03-10 17:22:424597// HttpRequestInfo request;
4598// request.method = "GET";
4599// request.url = GURL("http://www.google.com/");
4600// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:534601//
[email protected]a2cb8122010-03-10 17:22:424602// MockRead data_reads[] = {
4603// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4604// MockRead("hello world"),
4605// MockRead(true, OK),
4606// };
4607// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4608// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:534609//
[email protected]a2cb8122010-03-10 17:22:424610// SSLSocketDataProvider ssl(true, OK);
4611// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:534612//
[email protected]a2cb8122010-03-10 17:22:424613// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:534614//
[email protected]a2cb8122010-03-10 17:22:424615// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:534616//
[email protected]a2cb8122010-03-10 17:22:424617// HostPortPair http_host_port_pair;
4618// http_host_port_pair.host = "www.google.com";
4619// http_host_port_pair.port = 80;
4620// HttpAlternateProtocols* alternate_protocols =
4621// session->mutable_alternate_protocols();
4622// alternate_protocols->SetAlternateProtocolFor(
4623// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:064624// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:534625//
[email protected]a2cb8122010-03-10 17:22:424626// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:534627//
[email protected]a2cb8122010-03-10 17:22:424628// int rv = trans->Start(&request, &callback, NULL);
4629// EXPECT_EQ(ERR_IO_PENDING, rv);
4630// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:534631//
[email protected]a2cb8122010-03-10 17:22:424632// const HttpResponseInfo* response = trans->GetResponseInfo();
4633// ASSERT_TRUE(response != NULL);
4634// ASSERT_TRUE(response->headers != NULL);
4635// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:534636//
[email protected]a2cb8122010-03-10 17:22:424637// std::string response_data;
4638// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4639// EXPECT_EQ("hello world", response_data);
4640// }
4641
4642TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:064643 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:424644 SessionDependencies session_deps;
4645
4646 HttpRequestInfo request;
4647 request.method = "GET";
4648 request.url = GURL("http://www.google.com/");
4649 request.load_flags = 0;
4650
[email protected]a2cb8122010-03-10 17:22:424651 StaticSocketDataProvider first_tcp_connect;
4652 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
4653
4654 SSLSocketDataProvider ssl(true, OK);
4655 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4656
[email protected]564b4912010-03-09 16:30:424657 MockRead data_reads[] = {
4658 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4659 MockRead("hello world"),
4660 MockRead(true, OK),
4661 };
[email protected]a2cb8122010-03-10 17:22:424662 StaticSocketDataProvider fallback_data(
4663 data_reads, arraysize(data_reads), NULL, 0);
4664 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:424665
4666 TestCompletionCallback callback;
4667
4668 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4669
4670 HostPortPair http_host_port_pair;
4671 http_host_port_pair.host = "www.google.com";
4672 http_host_port_pair.port = 80;
4673 HttpAlternateProtocols* alternate_protocols =
4674 session->mutable_alternate_protocols();
4675 alternate_protocols->SetAlternateProtocolFor(
4676 http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:064677 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424678
4679 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4680
4681 int rv = trans->Start(&request, &callback, NULL);
4682 EXPECT_EQ(ERR_IO_PENDING, rv);
4683 EXPECT_EQ(OK, callback.WaitForResult());
4684
4685 const HttpResponseInfo* response = trans->GetResponseInfo();
4686 ASSERT_TRUE(response != NULL);
4687 ASSERT_TRUE(response->headers != NULL);
4688 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4689
4690 std::string response_data;
4691 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4692 EXPECT_EQ("hello world", response_data);
[email protected]31e2c69e2010-04-15 18:06:064693 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:424694}
4695
[email protected]e5ae96a2010-04-14 20:12:454696// MockAuthHandlerCanonical is used by the ResolveCanonicalName
4697// HttpNetworkTransaction unit test below. Callers set up expectations for
4698// whether the canonical name needs to be resolved.
4699class MockAuthHandlerCanonical : public HttpAuthHandler {
4700 public:
4701 enum Resolve {
4702 RESOLVE_INIT,
4703 RESOLVE_SKIP,
4704 RESOLVE_SYNC,
4705 RESOLVE_ASYNC,
4706 RESOLVE_TESTED,
4707 };
4708
4709 MockAuthHandlerCanonical() : resolve_(RESOLVE_INIT), user_callback_(NULL) {}
4710 virtual ~MockAuthHandlerCanonical() {}
4711
4712 void SetResolveExpectation(Resolve resolve) {
4713 EXPECT_EQ(RESOLVE_INIT, resolve_);
4714 resolve_ = resolve;
4715 }
4716
4717 void ResetResolveExpectation() {
4718 EXPECT_EQ(RESOLVE_TESTED, resolve_);
4719 resolve_ = RESOLVE_INIT;
4720 }
4721
4722 virtual bool NeedsCanonicalName() {
4723 switch (resolve_) {
4724 case RESOLVE_SYNC:
4725 case RESOLVE_ASYNC:
4726 return true;
4727 case RESOLVE_SKIP:
4728 resolve_ = RESOLVE_TESTED;
4729 return false;
4730 default:
4731 NOTREACHED();
4732 return false;
4733 }
4734 }
4735
4736 virtual int ResolveCanonicalName(HostResolver* host_resolver,
4737 CompletionCallback* callback,
4738 const BoundNetLog& net_log) {
4739 EXPECT_NE(RESOLVE_TESTED, resolve_);
4740 int rv = OK;
4741 switch (resolve_) {
4742 case RESOLVE_SYNC:
4743 resolve_ = RESOLVE_TESTED;
4744 break;
4745 case RESOLVE_ASYNC:
4746 EXPECT_TRUE(user_callback_ == NULL);
4747 rv = ERR_IO_PENDING;
4748 user_callback_ = callback;
4749 MessageLoop::current()->PostTask(
4750 FROM_HERE,
4751 NewRunnableMethod(
4752 this, &MockAuthHandlerCanonical::OnResolveCanonicalName));
4753 break;
4754 default:
4755 NOTREACHED();
4756 break;
4757 }
4758 return rv;
4759 }
4760
4761 void OnResolveCanonicalName() {
4762 EXPECT_EQ(RESOLVE_ASYNC, resolve_);
4763 EXPECT_TRUE(user_callback_ != NULL);
4764 resolve_ = RESOLVE_TESTED;
4765 CompletionCallback* callback = user_callback_;
4766 user_callback_ = NULL;
4767 callback->Run(OK);
4768 }
4769
4770 virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) {
4771 scheme_ = "mock";
4772 score_ = 1;
4773 properties_ = 0;
4774 return true;
4775 }
4776
4777 virtual int GenerateAuthToken(const std::wstring& username,
4778 const std::wstring& password,
4779 const HttpRequestInfo* request,
4780 const ProxyInfo* proxy,
4781 std::string* auth_token) {
4782 auth_token->assign("Mock AUTH myserver.example.com");
4783 return OK;
4784 }
4785
4786 virtual int GenerateDefaultAuthToken(const HttpRequestInfo* request,
4787 const ProxyInfo* proxy,
4788 std::string* auth_token) {
4789 auth_token->assign("Mock DEFAULT_AUTH myserver.example.com");
4790 return OK;
4791 }
4792
4793 // The Factory class simply returns the same handler each time
4794 // CreateAuthHandler is called.
4795 class Factory : public HttpAuthHandlerFactory {
4796 public:
4797 Factory() {}
4798 virtual ~Factory() {}
4799
4800 void set_mock_handler(MockAuthHandlerCanonical* mock_handler) {
4801 mock_handler_ = mock_handler;
4802 }
4803 MockAuthHandlerCanonical* mock_handler() const {
4804 return mock_handler_.get();
4805 }
4806
4807 virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
4808 HttpAuth::Target target,
4809 const GURL& origin,
4810 scoped_refptr<HttpAuthHandler>* handler) {
4811 *handler = mock_handler_;
4812 return OK;
4813 }
4814
4815 private:
4816 scoped_refptr<MockAuthHandlerCanonical> mock_handler_;
4817 };
4818
4819 private:
4820 Resolve resolve_;
4821 CompletionCallback* user_callback_;
4822};
4823
4824// Tests that ResolveCanonicalName is handled correctly by the
4825// HttpNetworkTransaction.
4826TEST_F(HttpNetworkTransactionTest, ResolveCanonicalName) {
4827 SessionDependencies session_deps;
4828 scoped_refptr<MockAuthHandlerCanonical> auth_handler(
4829 new MockAuthHandlerCanonical());
4830 auth_handler->Init(NULL);
4831 MockAuthHandlerCanonical::Factory* auth_factory(
4832 new MockAuthHandlerCanonical::Factory());
4833 auth_factory->set_mock_handler(auth_handler);
4834 session_deps.http_auth_handler_factory.reset(auth_factory);
4835
4836 for (int i = 0; i < 2; ++i) {
4837 scoped_ptr<HttpTransaction> trans(
4838 new HttpNetworkTransaction(CreateSession(&session_deps)));
4839
4840 // Set up expectations for this pass of the test. Many of the EXPECT calls
4841 // are contained inside the MockAuthHandlerCanonical codebase in response to
4842 // the expectations.
4843 MockAuthHandlerCanonical::Resolve resolve = (i == 0) ?
4844 MockAuthHandlerCanonical::RESOLVE_SYNC :
4845 MockAuthHandlerCanonical::RESOLVE_ASYNC;
4846 auth_handler->SetResolveExpectation(resolve);
4847 HttpRequestInfo request;
4848 request.method = "GET";
4849 request.url = GURL("http://myserver/");
4850 request.load_flags = 0;
4851
4852 MockWrite data_writes1[] = {
4853 MockWrite("GET / HTTP/1.1\r\n"
4854 "Host: myserver\r\n"
4855 "Connection: keep-alive\r\n\r\n"),
4856 };
4857
4858 MockRead data_reads1[] = {
4859 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4860 MockRead("WWW-Authenticate: Mock myserver.example.com\r\n"),
4861 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4862 MockRead("Content-Length: 14\r\n\r\n"),
4863 MockRead("Unauthorized\r\n"),
4864 };
4865
4866 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4867 data_writes1, arraysize(data_writes1));
4868 session_deps.socket_factory.AddSocketDataProvider(&data1);
4869
4870 TestCompletionCallback callback1;
4871
4872 int rv = trans->Start(&request, &callback1, NULL);
4873 EXPECT_EQ(ERR_IO_PENDING, rv);
4874
4875 rv = callback1.WaitForResult();
4876 EXPECT_EQ(OK, rv);
4877
4878 const HttpResponseInfo* response = trans->GetResponseInfo();
4879 EXPECT_FALSE(response == NULL);
4880
4881 // The password prompt is set after the canonical name is resolved.
4882 // If it isn't present or is incorrect, it indicates that the scheme
4883 // did not complete correctly.
4884 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4885
4886 EXPECT_EQ(L"myserver:80", response->auth_challenge->host_and_port);
4887 EXPECT_EQ(L"", response->auth_challenge->realm);
4888 EXPECT_EQ(L"mock", response->auth_challenge->scheme);
4889 auth_handler->ResetResolveExpectation();
4890 }
4891}
4892
[email protected]aeaca1f2010-04-20 22:05:214893class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
4894 public:
4895 TLSDecompressionFailureSocketDataProvider(bool fail_all)
4896 : fail_all_(fail_all) {
4897 }
4898
4899 virtual MockRead GetNextRead() {
4900 if (fail_all_)
4901 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
4902
4903 return MockRead(false /* async */,
4904 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
4905 }
4906
4907 virtual MockWriteResult OnWrite(const std::string& data) {
4908 return MockWriteResult(false /* async */, data.size());
4909 }
4910
4911 void Reset() {
4912 }
4913
4914 private:
4915 const bool fail_all_;
4916};
4917
4918// Test that we restart a connection when we see a decompression failure from
4919// the peer during the handshake. (In the real world we'll restart with SSLv3
4920// and we won't offer DEFLATE in that case.)
4921TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
4922 HttpRequestInfo request;
4923 request.method = "GET";
4924 request.url = GURL("https://tlsdecompressionfailure.example.com/");
4925 request.load_flags = 0;
4926
4927 SessionDependencies session_deps;
4928 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
4929 false /* fail all reads */);
4930 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
4931 SSLSocketDataProvider ssl_socket_data_provider1(
4932 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
4933 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
4934 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
4935 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
4936 session_deps.socket_factory.AddSSLSocketDataProvider(
4937 &ssl_socket_data_provider1);
4938 session_deps.socket_factory.AddSSLSocketDataProvider(
4939 &ssl_socket_data_provider2);
4940
4941 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4942 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4943 TestCompletionCallback callback;
4944
4945 int rv = trans->Start(&request, &callback, NULL);
4946 EXPECT_EQ(ERR_IO_PENDING, rv);
4947 EXPECT_EQ(OK, callback.WaitForResult());
4948
4949 const HttpResponseInfo* response = trans->GetResponseInfo();
4950 ASSERT_TRUE(response != NULL);
4951 ASSERT_TRUE(response->headers != NULL);
4952 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4953
4954 std::string response_data;
4955 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4956 EXPECT_EQ("ok.", response_data);
4957}
4958
4959// Test that we restart a connection if we get a decompression failure from the
4960// peer while reading the first bytes from the connection. This occurs when the
4961// peer cannot handle DEFLATE but we're using False Start, so we don't notice
4962// in the handshake.
4963TEST_F(HttpNetworkTransactionTest,
4964 RestartAfterTLSDecompressionFailureWithFalseStart) {
4965 HttpRequestInfo request;
4966 request.method = "GET";
4967 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
4968 request.load_flags = 0;
4969
4970 SessionDependencies session_deps;
4971 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
4972 true /* fail all reads */);
4973 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
4974 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
4975 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
4976 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
4977 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
4978 session_deps.socket_factory.AddSSLSocketDataProvider(
4979 &ssl_socket_data_provider1);
4980 session_deps.socket_factory.AddSSLSocketDataProvider(
4981 &ssl_socket_data_provider2);
4982
4983 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4984 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4985 TestCompletionCallback callback;
4986
4987 int rv = trans->Start(&request, &callback, NULL);
4988 EXPECT_EQ(ERR_IO_PENDING, rv);
4989 EXPECT_EQ(OK, callback.WaitForResult());
4990
4991 const HttpResponseInfo* response = trans->GetResponseInfo();
4992 ASSERT_TRUE(response != NULL);
4993 ASSERT_TRUE(response->headers != NULL);
4994 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4995
4996 std::string response_data;
4997 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4998 EXPECT_EQ("ok.", response_data);
4999}
5000
[email protected]89ceba9a2009-03-21 03:46:065001} // namespace net