blob: bef3237cada31eab6e36413751c2d4226724154f [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]fa55e192010-02-15 14:25:5046 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]955fc2e72010-02-08 20:37:3047 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]fa55e192010-02-15 14:25:5054 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]955fc2e72010-02-08 20:37:3055 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]955fc2e72010-02-08 20:37:3062 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
71
[email protected]228ff742009-06-05 01:19:5972HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]d13c3272010-02-04 00:24:5173 return new HttpNetworkSession(NULL,
74 session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:0975 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:4276 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:1077 session_deps->ssl_config_service,
[email protected]fa55e192010-02-15 14:25:5078 session_deps->spdy_session_pool,
79 session_deps->http_auth_handler_factory.get());
[email protected]e8d536192008-10-17 22:21:1480}
81
[email protected]89836e22008-09-25 20:33:4282class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:5283 public:
[email protected]0e75a732008-10-16 20:36:0984 virtual void TearDown() {
85 // Empty the current queue.
86 MessageLoop::current()->RunAllPending();
87 PlatformTest::TearDown();
88 }
89
[email protected]3d2a59b2008-09-26 19:44:2590 protected:
91 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:5292
[email protected]ff007e162009-05-23 09:13:1593 struct SimpleGetHelperResult {
94 int rv;
95 std::string status_line;
96 std::string response_data;
97 };
initial.commit586acc5fe2008-07-26 22:42:5298
[email protected]31a2bfe2010-02-09 08:03:3999 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
100 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15101 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52102
[email protected]228ff742009-06-05 01:19:59103 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40104 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43105 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52106
[email protected]ff007e162009-05-23 09:13:15107 HttpRequestInfo request;
108 request.method = "GET";
109 request.url = GURL("http://www.google.com/");
110 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52111
[email protected]31a2bfe2010-02-09 08:03:39112 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59113 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52114
[email protected]ff007e162009-05-23 09:13:15115 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52116
[email protected]684970b2009-08-14 04:54:46117 int rv = trans->Start(&request, &callback, NULL);
[email protected]ff007e162009-05-23 09:13:15118 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52119
[email protected]ff007e162009-05-23 09:13:15120 out.rv = callback.WaitForResult();
121 if (out.rv != OK)
122 return out;
123
124 const HttpResponseInfo* response = trans->GetResponseInfo();
125 EXPECT_TRUE(response != NULL);
126
127 EXPECT_TRUE(response->headers != NULL);
128 out.status_line = response->headers->GetStatusLine();
129
130 rv = ReadTransaction(trans.get(), &out.response_data);
131 EXPECT_EQ(OK, rv);
132
[email protected]aecfbf22008-10-16 02:02:47133 return out;
[email protected]ff007e162009-05-23 09:13:15134 }
initial.commit586acc5fe2008-07-26 22:42:52135
[email protected]ff007e162009-05-23 09:13:15136 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
137 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52138
[email protected]ff007e162009-05-23 09:13:15139 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15140};
[email protected]231d5a32008-09-13 00:45:27141
[email protected]15a5ccf82008-10-23 19:57:43142// Fill |str| with a long header list that consumes >= |size| bytes.
143void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19144 const char* row =
145 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
146 const int sizeof_row = strlen(row);
147 const int num_rows = static_cast<int>(
148 ceil(static_cast<float>(size) / sizeof_row));
149 const int sizeof_data = num_rows * sizeof_row;
150 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43151 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51152
[email protected]4ddaf2502008-10-23 18:26:19153 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43154 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19155}
156
[email protected]385a4672009-03-11 22:21:29157// Alternative functions that eliminate randomness and dependency on the local
158// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20159void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29160 static const uint8 bytes[] = {
161 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
162 };
163 static size_t current_byte = 0;
164 for (size_t i = 0; i < n; ++i) {
165 output[i] = bytes[current_byte++];
166 current_byte %= arraysize(bytes);
167 }
168}
169
[email protected]fe2bc6a2009-03-23 16:52:20170void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29171 static const uint8 bytes[] = {
172 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
173 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
174 };
175 static size_t current_byte = 0;
176 for (size_t i = 0; i < n; ++i) {
177 output[i] = bytes[current_byte++];
178 current_byte %= arraysize(bytes);
179 }
180}
181
[email protected]fe2bc6a2009-03-23 16:52:20182std::string MockGetHostName() {
183 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29184}
185
[email protected]a796bcec2010-03-22 17:17:26186template<typename EmulatedClientSocketPool, typename SocketSourceType>
187class CaptureGroupNameSocketPool : public EmulatedClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31188 public:
[email protected]a796bcec2010-03-22 17:17:26189 CaptureGroupNameSocketPool(HttpNetworkSession* session,
190 SocketSourceType* socket_source)
191 : EmulatedClientSocketPool(0, 0, "CaptureGroupNameTestPool",
192 session->host_resolver(), socket_source,
193 NULL) {}
[email protected]d80a4322009-08-14 07:07:49194 const std::string last_group_name_received() const {
195 return last_group_name_;
196 }
197
[email protected]684970b2009-08-14 04:54:46198 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49199 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31200 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31201 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46202 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53203 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31204 last_group_name_ = group_name;
205 return ERR_IO_PENDING;
206 }
[email protected]04e5be32009-06-26 20:00:31207 virtual void CancelRequest(const std::string& group_name,
208 const ClientSocketHandle* handle) { }
209 virtual void ReleaseSocket(const std::string& group_name,
210 ClientSocket* socket) {}
211 virtual void CloseIdleSockets() {}
212 virtual HostResolver* GetHostResolver() const {
213 return NULL;
214 }
215 virtual int IdleSocketCount() const {
216 return 0;
217 }
218 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
219 return 0;
220 }
221 virtual LoadState GetLoadState(const std::string& group_name,
222 const ClientSocketHandle* handle) const {
223 return LOAD_STATE_IDLE;
224 }
[email protected]a796bcec2010-03-22 17:17:26225 virtual base::TimeDelta ConnectionTimeout() const {
226 return base::TimeDelta();
227 }
[email protected]d80a4322009-08-14 07:07:49228
229 private:
[email protected]04e5be32009-06-26 20:00:31230 std::string last_group_name_;
231};
232
[email protected]a796bcec2010-03-22 17:17:26233typedef CaptureGroupNameSocketPool<TCPClientSocketPool, ClientSocketFactory>
234 CaptureGroupNameTCPSocketPool;
235typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool, TCPClientSocketPool>
236 CaptureGroupNameSOCKSSocketPool;
[email protected]231d5a32008-09-13 00:45:27237//-----------------------------------------------------------------------------
238
239TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59240 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40241 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43242 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27243}
244
245TEST_F(HttpNetworkTransactionTest, SimpleGET) {
246 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35247 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
248 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42249 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27250 };
[email protected]31a2bfe2010-02-09 08:03:39251 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
252 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42253 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27254 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
255 EXPECT_EQ("hello world", out.response_data);
256}
257
258// Response with no status line.
259TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
260 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35261 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42262 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27263 };
[email protected]31a2bfe2010-02-09 08:03:39264 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
265 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42266 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27267 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
268 EXPECT_EQ("hello world", out.response_data);
269}
270
271// Allow up to 4 bytes of junk to precede status line.
272TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
273 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35274 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42275 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27276 };
[email protected]31a2bfe2010-02-09 08:03:39277 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
278 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42279 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27280 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
281 EXPECT_EQ("DATA", out.response_data);
282}
283
284// Allow up to 4 bytes of junk to precede status line.
285TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
286 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35287 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42288 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27289 };
[email protected]31a2bfe2010-02-09 08:03:39290 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
291 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42292 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27293 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
294 EXPECT_EQ("DATA", out.response_data);
295}
296
297// Beyond 4 bytes of slop and it should fail to find a status line.
298TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
299 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35300 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42301 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27302 };
[email protected]31a2bfe2010-02-09 08:03:39303 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
304 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42305 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25306 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
307 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27308}
309
310// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
311TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
312 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35313 MockRead("\n"),
314 MockRead("\n"),
315 MockRead("Q"),
316 MockRead("J"),
317 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42318 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27319 };
[email protected]31a2bfe2010-02-09 08:03:39320 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
321 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42322 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27323 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
324 EXPECT_EQ("DATA", out.response_data);
325}
326
327// Close the connection before enough bytes to have a status line.
328TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
329 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35330 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42331 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27332 };
[email protected]31a2bfe2010-02-09 08:03:39333 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
334 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42335 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27336 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
337 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52338}
339
[email protected]f9d44aa2008-09-23 23:57:17340// Simulate a 204 response, lacking a Content-Length header, sent over a
341// persistent connection. The response should still terminate since a 204
342// cannot have a response body.
343TEST_F(HttpNetworkTransactionTest, StopsReading204) {
344 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35345 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
346 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42347 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17348 };
[email protected]31a2bfe2010-02-09 08:03:39349 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
350 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42351 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17352 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
353 EXPECT_EQ("", out.response_data);
354}
355
[email protected]0877e3d2009-10-17 22:29:57356// A simple request using chunked encoding with some extra data after.
357// (Like might be seen in a pipelined response.)
358TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
359 MockRead data_reads[] = {
360 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
361 MockRead("5\r\nHello\r\n"),
362 MockRead("1\r\n"),
363 MockRead(" \r\n"),
364 MockRead("5\r\nworld\r\n"),
365 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
366 MockRead(false, OK),
367 };
[email protected]31a2bfe2010-02-09 08:03:39368 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
369 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57370 EXPECT_EQ(OK, out.rv);
371 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
372 EXPECT_EQ("Hello world", out.response_data);
373}
374
[email protected]ef0faf2e72009-03-05 23:27:23375// Do a request using the HEAD method. Verify that we don't try to read the
376// message body (since HEAD has none).
377TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59378 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40379 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43380 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23381
[email protected]1c773ea12009-04-28 19:58:42382 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23383 request.method = "HEAD";
384 request.url = GURL("http://www.google.com/");
385 request.load_flags = 0;
386
387 MockWrite data_writes1[] = {
388 MockWrite("HEAD / HTTP/1.1\r\n"
389 "Host: www.google.com\r\n"
390 "Connection: keep-alive\r\n"
391 "Content-Length: 0\r\n\r\n"),
392 };
393 MockRead data_reads1[] = {
394 MockRead("HTTP/1.1 404 Not Found\r\n"),
395 MockRead("Server: Blah\r\n"),
396 MockRead("Content-Length: 1234\r\n\r\n"),
397
398 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42399 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23400 };
401
[email protected]31a2bfe2010-02-09 08:03:39402 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
403 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59404 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23405
406 TestCompletionCallback callback1;
407
[email protected]684970b2009-08-14 04:54:46408 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42409 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23410
411 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42412 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23413
[email protected]1c773ea12009-04-28 19:58:42414 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23415 EXPECT_FALSE(response == NULL);
416
417 // Check that the headers got parsed.
418 EXPECT_TRUE(response->headers != NULL);
419 EXPECT_EQ(1234, response->headers->GetContentLength());
420 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
421
422 std::string server_header;
423 void* iter = NULL;
424 bool has_server_header = response->headers->EnumerateHeader(
425 &iter, "Server", &server_header);
426 EXPECT_TRUE(has_server_header);
427 EXPECT_EQ("Blah", server_header);
428
429 // Reading should give EOF right away, since there is no message body
430 // (despite non-zero content-length).
431 std::string response_data;
432 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42433 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23434 EXPECT_EQ("", response_data);
435}
436
initial.commit586acc5fe2008-07-26 22:42:52437TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59438 SessionDependencies session_deps;
439 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52440
441 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35442 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
443 MockRead("hello"),
444 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
445 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42446 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52447 };
[email protected]31a2bfe2010-02-09 08:03:39448 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59449 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52450
451 const char* kExpectedResponseData[] = {
452 "hello", "world"
453 };
454
455 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43456 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52457
[email protected]1c773ea12009-04-28 19:58:42458 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52459 request.method = "GET";
460 request.url = GURL("http://www.google.com/");
461 request.load_flags = 0;
462
463 TestCompletionCallback callback;
464
[email protected]684970b2009-08-14 04:54:46465 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42466 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52467
468 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42469 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52470
[email protected]1c773ea12009-04-28 19:58:42471 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52472 EXPECT_TRUE(response != NULL);
473
474 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25475 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52476
477 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57478 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42479 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25480 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52481 }
482}
483
484TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59485 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40486 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43487 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52488
[email protected]1c773ea12009-04-28 19:58:42489 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52490 request.method = "POST";
491 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42492 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52493 request.upload_data->AppendBytes("foo", 3);
494 request.load_flags = 0;
495
496 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35497 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
498 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
499 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42500 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52501 };
[email protected]31a2bfe2010-02-09 08:03:39502 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59503 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52504
505 TestCompletionCallback callback;
506
[email protected]684970b2009-08-14 04:54:46507 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42508 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52509
510 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42511 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52512
[email protected]1c773ea12009-04-28 19:58:42513 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52514 EXPECT_TRUE(response != NULL);
515
516 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25517 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52518
519 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57520 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42521 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25522 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52523}
524
[email protected]3a2d3662009-03-27 03:49:14525// This test is almost the same as Ignores100 above, but the response contains
526// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57527// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14528TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59529 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40530 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43531 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14532
[email protected]1c773ea12009-04-28 19:58:42533 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14534 request.method = "GET";
535 request.url = GURL("http://www.foo.com/");
536 request.load_flags = 0;
537
538 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57539 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
540 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14541 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42542 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14543 };
[email protected]31a2bfe2010-02-09 08:03:39544 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59545 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14546
547 TestCompletionCallback callback;
548
[email protected]684970b2009-08-14 04:54:46549 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42550 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14551
552 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42553 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14554
[email protected]1c773ea12009-04-28 19:58:42555 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14556 EXPECT_TRUE(response != NULL);
557
558 EXPECT_TRUE(response->headers != NULL);
559 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
560
561 std::string response_data;
562 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42563 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14564 EXPECT_EQ("hello world", response_data);
565}
566
[email protected]ee9410e72010-01-07 01:42:38567TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
568 SessionDependencies session_deps;
569 scoped_ptr<HttpTransaction> trans(
570 new HttpNetworkTransaction(CreateSession(&session_deps)));
571
572 HttpRequestInfo request;
573 request.method = "POST";
574 request.url = GURL("http://www.foo.com/");
575 request.load_flags = 0;
576
577 MockRead data_reads[] = {
578 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
579 MockRead(true, 0),
580 };
[email protected]31a2bfe2010-02-09 08:03:39581 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38582 session_deps.socket_factory.AddSocketDataProvider(&data);
583
584 TestCompletionCallback callback;
585
586 int rv = trans->Start(&request, &callback, NULL);
587 EXPECT_EQ(ERR_IO_PENDING, rv);
588
589 rv = callback.WaitForResult();
590 EXPECT_EQ(OK, rv);
591
592 std::string response_data;
593 rv = ReadTransaction(trans.get(), &response_data);
594 EXPECT_EQ(OK, rv);
595 EXPECT_EQ("", response_data);
596}
597
598TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
599 SessionDependencies session_deps;
600 scoped_ptr<HttpTransaction> trans(
601 new HttpNetworkTransaction(CreateSession(&session_deps)));
602
603 HttpRequestInfo request;
604 request.method = "POST";
605 request.url = GURL("http://www.foo.com/");
606 request.load_flags = 0;
607
608 MockRead data_reads[] = {
609 MockRead(true, 0),
610 };
[email protected]31a2bfe2010-02-09 08:03:39611 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38612 session_deps.socket_factory.AddSocketDataProvider(&data);
613
614 TestCompletionCallback callback;
615
616 int rv = trans->Start(&request, &callback, NULL);
617 EXPECT_EQ(ERR_IO_PENDING, rv);
618
619 rv = callback.WaitForResult();
620 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
621}
622
[email protected]3d2a59b2008-09-26 19:44:25623// read_failure specifies a read failure that should cause the network
624// transaction to resend the request.
625void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
626 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59627 SessionDependencies session_deps;
628 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52629
[email protected]1c773ea12009-04-28 19:58:42630 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52631 request.method = "GET";
632 request.url = GURL("http://www.foo.com/");
633 request.load_flags = 0;
634
635 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35636 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
637 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25638 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52639 };
[email protected]31a2bfe2010-02-09 08:03:39640 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59641 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52642
643 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35644 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
645 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42646 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52647 };
[email protected]31a2bfe2010-02-09 08:03:39648 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59649 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52650
651 const char* kExpectedResponseData[] = {
652 "hello", "world"
653 };
654
655 for (int i = 0; i < 2; ++i) {
656 TestCompletionCallback callback;
657
[email protected]5695b8c2009-09-30 21:36:43658 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52659
[email protected]684970b2009-08-14 04:54:46660 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42661 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52662
663 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42664 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52665
[email protected]1c773ea12009-04-28 19:58:42666 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52667 EXPECT_TRUE(response != NULL);
668
669 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25670 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52671
672 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57673 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42674 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25675 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52676 }
677}
[email protected]3d2a59b2008-09-26 19:44:25678
679TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42680 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25681 KeepAliveConnectionResendRequestTest(read_failure);
682}
683
684TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42685 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25686 KeepAliveConnectionResendRequestTest(read_failure);
687}
688
689TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59690 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40691 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43692 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25693
[email protected]1c773ea12009-04-28 19:58:42694 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25695 request.method = "GET";
696 request.url = GURL("http://www.google.com/");
697 request.load_flags = 0;
698
699 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42700 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35701 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
702 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42703 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25704 };
[email protected]31a2bfe2010-02-09 08:03:39705 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59706 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25707
708 TestCompletionCallback callback;
709
[email protected]684970b2009-08-14 04:54:46710 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42711 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25712
713 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42714 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25715
[email protected]1c773ea12009-04-28 19:58:42716 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25717 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25718}
719
720// What do various browsers do when the server closes a non-keepalive
721// connection without sending any response header or body?
722//
723// IE7: error page
724// Safari 3.1.2 (Windows): error page
725// Firefox 3.0.1: blank page
726// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42727// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
728// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25729TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
730 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42731 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35732 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
733 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42734 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25735 };
[email protected]31a2bfe2010-02-09 08:03:39736 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
737 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42738 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25739}
[email protected]038e9a32008-10-08 22:40:16740
741// Test the request-challenge-retry sequence for basic auth.
742// (basic auth is the easiest to mock, because it has no randomness).
743TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59744 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40745 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43746 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16747
[email protected]1c773ea12009-04-28 19:58:42748 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16749 request.method = "GET";
750 request.url = GURL("http://www.google.com/");
751 request.load_flags = 0;
752
[email protected]f9ee6b52008-11-08 06:46:23753 MockWrite data_writes1[] = {
754 MockWrite("GET / HTTP/1.1\r\n"
755 "Host: www.google.com\r\n"
756 "Connection: keep-alive\r\n\r\n"),
757 };
758
[email protected]038e9a32008-10-08 22:40:16759 MockRead data_reads1[] = {
760 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
761 // Give a couple authenticate options (only the middle one is actually
762 // supported).
[email protected]22927ad2009-09-21 19:56:19763 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16764 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
765 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
766 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
767 // Large content-length -- won't matter, as connection will be reset.
768 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42769 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16770 };
771
772 // After calling trans->RestartWithAuth(), this is the request we should
773 // be issuing -- the final header line contains the credentials.
774 MockWrite data_writes2[] = {
775 MockWrite("GET / HTTP/1.1\r\n"
776 "Host: www.google.com\r\n"
777 "Connection: keep-alive\r\n"
778 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
779 };
780
781 // Lastly, the server responds with the actual content.
782 MockRead data_reads2[] = {
783 MockRead("HTTP/1.0 200 OK\r\n"),
784 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
785 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42786 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16787 };
788
[email protected]31a2bfe2010-02-09 08:03:39789 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
790 data_writes1, arraysize(data_writes1));
791 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
792 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59793 session_deps.socket_factory.AddSocketDataProvider(&data1);
794 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16795
796 TestCompletionCallback callback1;
797
[email protected]684970b2009-08-14 04:54:46798 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42799 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16800
801 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42802 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16803
[email protected]1c773ea12009-04-28 19:58:42804 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16805 EXPECT_FALSE(response == NULL);
806
807 // The password prompt info should have been set in response->auth_challenge.
808 EXPECT_FALSE(response->auth_challenge.get() == NULL);
809
[email protected]71e4573a2009-05-21 22:03:00810 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16811 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
812 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
813
814 TestCompletionCallback callback2;
815
816 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42817 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16818
819 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42820 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16821
822 response = trans->GetResponseInfo();
823 EXPECT_FALSE(response == NULL);
824 EXPECT_TRUE(response->auth_challenge.get() == NULL);
825 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16826}
827
[email protected]861fcd52009-08-26 02:33:46828TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
829 SessionDependencies session_deps;
830 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43831 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46832
833 HttpRequestInfo request;
834 request.method = "GET";
835 request.url = GURL("http://www.google.com/");
836 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
837
838 MockWrite data_writes[] = {
839 MockWrite("GET / HTTP/1.1\r\n"
840 "Host: www.google.com\r\n"
841 "Connection: keep-alive\r\n\r\n"),
842 };
843
844 MockRead data_reads[] = {
845 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
846 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
847 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
848 // Large content-length -- won't matter, as connection will be reset.
849 MockRead("Content-Length: 10000\r\n\r\n"),
850 MockRead(false, ERR_FAILED),
851 };
852
[email protected]31a2bfe2010-02-09 08:03:39853 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
854 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59855 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46856 TestCompletionCallback callback;
857
858 int rv = trans->Start(&request, &callback, NULL);
859 EXPECT_EQ(ERR_IO_PENDING, rv);
860
861 rv = callback.WaitForResult();
862 EXPECT_EQ(0, rv);
863
864 const HttpResponseInfo* response = trans->GetResponseInfo();
865 ASSERT_FALSE(response == NULL);
866 EXPECT_TRUE(response->auth_challenge.get() == NULL);
867}
868
[email protected]2d2697f92009-02-18 21:00:32869// Test the request-challenge-retry sequence for basic auth, over a keep-alive
870// connection.
871TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59872 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40873 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43874 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32875
[email protected]1c773ea12009-04-28 19:58:42876 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32877 request.method = "GET";
878 request.url = GURL("http://www.google.com/");
879 request.load_flags = 0;
880
881 MockWrite data_writes1[] = {
882 MockWrite("GET / HTTP/1.1\r\n"
883 "Host: www.google.com\r\n"
884 "Connection: keep-alive\r\n\r\n"),
885
886 // After calling trans->RestartWithAuth(), this is the request we should
887 // be issuing -- the final header line contains the credentials.
888 MockWrite("GET / HTTP/1.1\r\n"
889 "Host: www.google.com\r\n"
890 "Connection: keep-alive\r\n"
891 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
892 };
893
894 MockRead data_reads1[] = {
895 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
896 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
897 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
898 MockRead("Content-Length: 14\r\n\r\n"),
899 MockRead("Unauthorized\r\n"),
900
901 // Lastly, the server responds with the actual content.
902 MockRead("HTTP/1.1 200 OK\r\n"),
903 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
904 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42905 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32906 };
907
[email protected]31a2bfe2010-02-09 08:03:39908 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
909 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59910 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32911
912 TestCompletionCallback callback1;
913
[email protected]684970b2009-08-14 04:54:46914 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42915 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32916
917 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42918 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32919
[email protected]1c773ea12009-04-28 19:58:42920 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32921 EXPECT_FALSE(response == NULL);
922
923 // The password prompt info should have been set in response->auth_challenge.
924 EXPECT_FALSE(response->auth_challenge.get() == NULL);
925
[email protected]71e4573a2009-05-21 22:03:00926 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32927 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
928 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
929
930 TestCompletionCallback callback2;
931
932 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42933 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32934
935 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42936 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32937
938 response = trans->GetResponseInfo();
939 EXPECT_FALSE(response == NULL);
940 EXPECT_TRUE(response->auth_challenge.get() == NULL);
941 EXPECT_EQ(100, response->headers->GetContentLength());
942}
943
944// Test the request-challenge-retry sequence for basic auth, over a keep-alive
945// connection and with no response body to drain.
946TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59947 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40948 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43949 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32950
[email protected]1c773ea12009-04-28 19:58:42951 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32952 request.method = "GET";
953 request.url = GURL("http://www.google.com/");
954 request.load_flags = 0;
955
956 MockWrite data_writes1[] = {
957 MockWrite("GET / HTTP/1.1\r\n"
958 "Host: www.google.com\r\n"
959 "Connection: keep-alive\r\n\r\n"),
960
961 // After calling trans->RestartWithAuth(), this is the request we should
962 // be issuing -- the final header line contains the credentials.
963 MockWrite("GET / HTTP/1.1\r\n"
964 "Host: www.google.com\r\n"
965 "Connection: keep-alive\r\n"
966 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
967 };
968
[email protected]2d2697f92009-02-18 21:00:32969 MockRead data_reads1[] = {
970 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
971 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:31972 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:32973
974 // Lastly, the server responds with the actual content.
975 MockRead("HTTP/1.1 200 OK\r\n"),
976 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
977 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42978 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32979 };
980
[email protected]31a2bfe2010-02-09 08:03:39981 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
982 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59983 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32984
985 TestCompletionCallback callback1;
986
[email protected]684970b2009-08-14 04:54:46987 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42988 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32989
990 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42991 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32992
[email protected]1c773ea12009-04-28 19:58:42993 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32994 EXPECT_FALSE(response == NULL);
995
996 // The password prompt info should have been set in response->auth_challenge.
997 EXPECT_FALSE(response->auth_challenge.get() == NULL);
998
[email protected]71e4573a2009-05-21 22:03:00999 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321000 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1001 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1002
1003 TestCompletionCallback callback2;
1004
1005 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421006 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321007
1008 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421009 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321010
1011 response = trans->GetResponseInfo();
1012 EXPECT_FALSE(response == NULL);
1013 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1014 EXPECT_EQ(100, response->headers->GetContentLength());
1015}
1016
1017// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1018// connection and with a large response body to drain.
1019TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591020 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401021 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431022 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321023
[email protected]1c773ea12009-04-28 19:58:421024 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321025 request.method = "GET";
1026 request.url = GURL("http://www.google.com/");
1027 request.load_flags = 0;
1028
1029 MockWrite data_writes1[] = {
1030 MockWrite("GET / HTTP/1.1\r\n"
1031 "Host: www.google.com\r\n"
1032 "Connection: keep-alive\r\n\r\n"),
1033
1034 // After calling trans->RestartWithAuth(), this is the request we should
1035 // be issuing -- the final header line contains the credentials.
1036 MockWrite("GET / HTTP/1.1\r\n"
1037 "Host: www.google.com\r\n"
1038 "Connection: keep-alive\r\n"
1039 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1040 };
1041
1042 // Respond with 5 kb of response body.
1043 std::string large_body_string("Unauthorized");
1044 large_body_string.append(5 * 1024, ' ');
1045 large_body_string.append("\r\n");
1046
1047 MockRead data_reads1[] = {
1048 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1049 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1050 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1051 // 5134 = 12 + 5 * 1024 + 2
1052 MockRead("Content-Length: 5134\r\n\r\n"),
1053 MockRead(true, large_body_string.data(), large_body_string.size()),
1054
1055 // Lastly, the server responds with the actual content.
1056 MockRead("HTTP/1.1 200 OK\r\n"),
1057 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1058 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421059 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321060 };
1061
[email protected]31a2bfe2010-02-09 08:03:391062 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1063 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591064 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321065
1066 TestCompletionCallback callback1;
1067
[email protected]684970b2009-08-14 04:54:461068 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421069 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321070
1071 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421072 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321073
[email protected]1c773ea12009-04-28 19:58:421074 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321075 EXPECT_FALSE(response == NULL);
1076
1077 // The password prompt info should have been set in response->auth_challenge.
1078 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1079
[email protected]71e4573a2009-05-21 22:03:001080 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321081 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1082 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1083
1084 TestCompletionCallback callback2;
1085
1086 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421087 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321088
1089 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421090 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321091
1092 response = trans->GetResponseInfo();
1093 EXPECT_FALSE(response == NULL);
1094 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1095 EXPECT_EQ(100, response->headers->GetContentLength());
1096}
1097
1098// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311099// connection, but the server gets impatient and closes the connection.
1100TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1101 SessionDependencies session_deps;
1102 scoped_ptr<HttpTransaction> trans(
1103 new HttpNetworkTransaction(CreateSession(&session_deps)));
1104
1105 HttpRequestInfo request;
1106 request.method = "GET";
1107 request.url = GURL("http://www.google.com/");
1108 request.load_flags = 0;
1109
1110 MockWrite data_writes1[] = {
1111 MockWrite("GET / HTTP/1.1\r\n"
1112 "Host: www.google.com\r\n"
1113 "Connection: keep-alive\r\n\r\n"),
1114 // This simulates the seemingly successful write to a closed connection
1115 // if the bug is not fixed.
1116 MockWrite("GET / HTTP/1.1\r\n"
1117 "Host: www.google.com\r\n"
1118 "Connection: keep-alive\r\n"
1119 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1120 };
1121
1122 MockRead data_reads1[] = {
1123 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1124 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1125 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1126 MockRead("Content-Length: 14\r\n\r\n"),
1127 // Tell MockTCPClientSocket to simulate the server closing the connection.
1128 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1129 MockRead("Unauthorized\r\n"),
1130 MockRead(false, OK), // The server closes the connection.
1131 };
1132
1133 // After calling trans->RestartWithAuth(), this is the request we should
1134 // be issuing -- the final header line contains the credentials.
1135 MockWrite data_writes2[] = {
1136 MockWrite("GET / HTTP/1.1\r\n"
1137 "Host: www.google.com\r\n"
1138 "Connection: keep-alive\r\n"
1139 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1140 };
1141
1142 // Lastly, the server responds with the actual content.
1143 MockRead data_reads2[] = {
1144 MockRead("HTTP/1.1 200 OK\r\n"),
1145 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1146 MockRead("Content-Length: 100\r\n\r\n"),
1147 MockRead(false, OK),
1148 };
1149
[email protected]31a2bfe2010-02-09 08:03:391150 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1151 data_writes1, arraysize(data_writes1));
1152 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1153 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311154 session_deps.socket_factory.AddSocketDataProvider(&data1);
1155 session_deps.socket_factory.AddSocketDataProvider(&data2);
1156
1157 TestCompletionCallback callback1;
1158
1159 int rv = trans->Start(&request, &callback1, NULL);
1160 EXPECT_EQ(ERR_IO_PENDING, rv);
1161
1162 rv = callback1.WaitForResult();
1163 EXPECT_EQ(OK, rv);
1164
1165 const HttpResponseInfo* response = trans->GetResponseInfo();
1166 EXPECT_FALSE(response == NULL);
1167
1168 // The password prompt info should have been set in response->auth_challenge.
1169 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1170
1171 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1172 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1173 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1174
1175 TestCompletionCallback callback2;
1176
1177 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1178 EXPECT_EQ(ERR_IO_PENDING, rv);
1179
1180 rv = callback2.WaitForResult();
1181 EXPECT_EQ(OK, rv);
1182
1183 response = trans->GetResponseInfo();
1184 ASSERT_FALSE(response == NULL);
1185 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1186 EXPECT_EQ(100, response->headers->GetContentLength());
1187}
1188
1189// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321190// proxy connection, when setting up an SSL tunnel.
1191TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1192 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591193 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1194 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321195
[email protected]5695b8c2009-09-30 21:36:431196 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321197
[email protected]1c773ea12009-04-28 19:58:421198 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321199 request.method = "GET";
1200 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461201 // Ensure that proxy authentication is attempted even
1202 // when the no authentication data flag is set.
1203 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321204
1205 // Since we have proxy, should try to establish tunnel.
1206 MockWrite data_writes1[] = {
1207 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451208 "Host: www.google.com\r\n"
1209 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321210
1211 // After calling trans->RestartWithAuth(), this is the request we should
1212 // be issuing -- the final header line contains the credentials.
1213 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1214 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451215 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321216 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1217 };
1218
1219 // The proxy responds to the connect with a 407, using a persistent
1220 // connection.
1221 MockRead data_reads1[] = {
1222 // No credentials.
1223 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1224 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1225 MockRead("Content-Length: 10\r\n\r\n"),
1226 MockRead("0123456789"),
1227
1228 // Wrong credentials (wrong password).
1229 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1230 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1231 MockRead("Content-Length: 10\r\n\r\n"),
1232 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421233 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321234 };
1235
[email protected]31a2bfe2010-02-09 08:03:391236 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1237 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591238 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321239
1240 TestCompletionCallback callback1;
1241
[email protected]684970b2009-08-14 04:54:461242 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421243 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321244
1245 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421246 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321247
[email protected]1c773ea12009-04-28 19:58:421248 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321249 EXPECT_FALSE(response == NULL);
1250
1251 EXPECT_TRUE(response->headers->IsKeepAlive());
1252 EXPECT_EQ(407, response->headers->response_code());
1253 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421254 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321255
1256 // The password prompt info should have been set in response->auth_challenge.
1257 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1258
[email protected]71e4573a2009-05-21 22:03:001259 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321260 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1261 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1262
1263 TestCompletionCallback callback2;
1264
1265 // Wrong password (should be "bar").
1266 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421267 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321268
1269 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421270 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321271
1272 response = trans->GetResponseInfo();
1273 EXPECT_FALSE(response == NULL);
1274
1275 EXPECT_TRUE(response->headers->IsKeepAlive());
1276 EXPECT_EQ(407, response->headers->response_code());
1277 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421278 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321279
1280 // The password prompt info should have been set in response->auth_challenge.
1281 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1282
[email protected]71e4573a2009-05-21 22:03:001283 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321284 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1285 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1286}
1287
[email protected]a8e9b162009-03-12 00:06:441288// Test that we don't read the response body when we fail to establish a tunnel,
1289// even if the user cancels the proxy's auth attempt.
1290TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1291 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591292 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441293
[email protected]e44de5d2009-06-05 20:12:451294 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441295
[email protected]5695b8c2009-09-30 21:36:431296 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441297
[email protected]1c773ea12009-04-28 19:58:421298 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441299 request.method = "GET";
1300 request.url = GURL("https://www.google.com/");
1301 request.load_flags = 0;
1302
1303 // Since we have proxy, should try to establish tunnel.
1304 MockWrite data_writes[] = {
1305 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451306 "Host: www.google.com\r\n"
1307 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441308 };
1309
1310 // The proxy responds to the connect with a 407.
1311 MockRead data_reads[] = {
1312 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1313 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1314 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421315 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441316 };
1317
[email protected]31a2bfe2010-02-09 08:03:391318 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1319 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591320 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441321
1322 TestCompletionCallback callback;
1323
[email protected]684970b2009-08-14 04:54:461324 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421325 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441326
1327 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421328 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441329
[email protected]1c773ea12009-04-28 19:58:421330 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441331 EXPECT_FALSE(response == NULL);
1332
1333 EXPECT_TRUE(response->headers->IsKeepAlive());
1334 EXPECT_EQ(407, response->headers->response_code());
1335 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421336 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441337
1338 std::string response_data;
1339 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421340 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441341}
1342
[email protected]ff007e162009-05-23 09:13:151343void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081344 const MockRead& status, int expected_status) {
1345 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591346 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081347
[email protected]228ff742009-06-05 01:19:591348 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081349
[email protected]5695b8c2009-09-30 21:36:431350 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081351
[email protected]1c773ea12009-04-28 19:58:421352 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081353 request.method = "GET";
1354 request.url = GURL("https://www.google.com/");
1355 request.load_flags = 0;
1356
1357 // Since we have proxy, should try to establish tunnel.
1358 MockWrite data_writes[] = {
1359 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451360 "Host: www.google.com\r\n"
1361 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081362 };
1363
1364 MockRead data_reads[] = {
1365 status,
1366 MockRead("Content-Length: 10\r\n\r\n"),
1367 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421368 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081369 };
1370
[email protected]31a2bfe2010-02-09 08:03:391371 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1372 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591373 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081374
1375 TestCompletionCallback callback;
1376
[email protected]684970b2009-08-14 04:54:461377 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421378 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081379
1380 rv = callback.WaitForResult();
1381 EXPECT_EQ(expected_status, rv);
1382}
1383
[email protected]ff007e162009-05-23 09:13:151384void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081385 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421386 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081387}
1388
1389TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1390 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1391}
1392
1393TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1394 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1395}
1396
1397TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1398 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1399}
1400
1401TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1402 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1403}
1404
1405TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1406 ConnectStatusHelper(
1407 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1408}
1409
1410TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1411 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1412}
1413
1414TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1415 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1416}
1417
1418TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1419 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1420}
1421
1422TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1423 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1424}
1425
1426TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1427 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1428}
1429
1430TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1431 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1432}
1433
1434TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1435 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1436}
1437
1438TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1439 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1440}
1441
1442TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1443 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1444}
1445
1446TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1447 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1448}
1449
1450TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1451 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1452}
1453
1454TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1455 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1456}
1457
1458TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1459 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1460}
1461
1462TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1463 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1464}
1465
1466TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1467 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1468}
1469
1470TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1471 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1472}
1473
1474TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1475 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1476}
1477
1478TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1479 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1480}
1481
1482TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1483 ConnectStatusHelperWithExpectedStatus(
1484 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421485 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081486}
1487
1488TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1489 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1490}
1491
1492TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1493 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1494}
1495
1496TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1497 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1498}
1499
1500TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1501 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1502}
1503
1504TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1505 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1506}
1507
1508TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1509 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1510}
1511
1512TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1513 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1514}
1515
1516TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1517 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1518}
1519
1520TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1521 ConnectStatusHelper(
1522 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1523}
1524
1525TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1526 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1527}
1528
1529TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1530 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1531}
1532
1533TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1534 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1535}
1536
1537TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1538 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1539}
1540
1541TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1542 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1543}
1544
1545TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1546 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1547}
1548
1549TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1550 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1551}
1552
[email protected]038e9a32008-10-08 22:40:161553// Test the flow when both the proxy server AND origin server require
1554// authentication. Again, this uses basic auth for both since that is
1555// the simplest to mock.
1556TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591557 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011558
[email protected]038e9a32008-10-08 22:40:161559 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421560 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431561 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161562
[email protected]1c773ea12009-04-28 19:58:421563 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161564 request.method = "GET";
1565 request.url = GURL("http://www.google.com/");
1566 request.load_flags = 0;
1567
[email protected]f9ee6b52008-11-08 06:46:231568 MockWrite data_writes1[] = {
1569 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1570 "Host: www.google.com\r\n"
1571 "Proxy-Connection: keep-alive\r\n\r\n"),
1572 };
1573
[email protected]038e9a32008-10-08 22:40:161574 MockRead data_reads1[] = {
1575 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1576 // Give a couple authenticate options (only the middle one is actually
1577 // supported).
[email protected]22927ad2009-09-21 19:56:191578 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161579 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1580 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1581 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1582 // Large content-length -- won't matter, as connection will be reset.
1583 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421584 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161585 };
1586
1587 // After calling trans->RestartWithAuth() the first time, this is the
1588 // request we should be issuing -- the final header line contains the
1589 // proxy's credentials.
1590 MockWrite data_writes2[] = {
1591 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1592 "Host: www.google.com\r\n"
1593 "Proxy-Connection: keep-alive\r\n"
1594 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1595 };
1596
1597 // Now the proxy server lets the request pass through to origin server.
1598 // The origin server responds with a 401.
1599 MockRead data_reads2[] = {
1600 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1601 // Note: We are using the same realm-name as the proxy server. This is
1602 // completely valid, as realms are unique across hosts.
1603 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1604 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1605 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421606 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161607 };
1608
1609 // After calling trans->RestartWithAuth() the second time, we should send
1610 // the credentials for both the proxy and origin server.
1611 MockWrite data_writes3[] = {
1612 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1613 "Host: www.google.com\r\n"
1614 "Proxy-Connection: keep-alive\r\n"
1615 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1616 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1617 };
1618
1619 // Lastly we get the desired content.
1620 MockRead data_reads3[] = {
1621 MockRead("HTTP/1.0 200 OK\r\n"),
1622 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1623 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421624 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161625 };
1626
[email protected]31a2bfe2010-02-09 08:03:391627 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1628 data_writes1, arraysize(data_writes1));
1629 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1630 data_writes2, arraysize(data_writes2));
1631 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1632 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591633 session_deps.socket_factory.AddSocketDataProvider(&data1);
1634 session_deps.socket_factory.AddSocketDataProvider(&data2);
1635 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161636
1637 TestCompletionCallback callback1;
1638
[email protected]684970b2009-08-14 04:54:461639 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421640 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161641
1642 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421643 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161644
[email protected]1c773ea12009-04-28 19:58:421645 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161646 EXPECT_FALSE(response == NULL);
1647
1648 // The password prompt info should have been set in response->auth_challenge.
1649 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1650
[email protected]71e4573a2009-05-21 22:03:001651 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161652 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1653 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1654
1655 TestCompletionCallback callback2;
1656
1657 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421658 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161659
1660 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421661 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161662
1663 response = trans->GetResponseInfo();
1664 EXPECT_FALSE(response == NULL);
1665 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1666
[email protected]71e4573a2009-05-21 22:03:001667 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161668 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1669 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1670
1671 TestCompletionCallback callback3;
1672
1673 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421674 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161675
1676 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421677 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161678
1679 response = trans->GetResponseInfo();
1680 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1681 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161682}
[email protected]4ddaf2502008-10-23 18:26:191683
[email protected]ea9dc9a2009-09-05 00:43:321684// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1685// can't hook into its internals to cause it to generate predictable NTLM
1686// authorization headers.
1687#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291688// The NTLM authentication unit tests were generated by capturing the HTTP
1689// requests and responses using Fiddler 2 and inspecting the generated random
1690// bytes in the debugger.
1691
1692// Enter the correct password and authenticate successfully.
1693TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421694 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201695 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591696 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401697 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431698 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241699
[email protected]1c773ea12009-04-28 19:58:421700 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241701 request.method = "GET";
1702 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1703 request.load_flags = 0;
1704
1705 MockWrite data_writes1[] = {
1706 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1707 "Host: 172.22.68.17\r\n"
1708 "Connection: keep-alive\r\n\r\n"),
1709 };
1710
1711 MockRead data_reads1[] = {
1712 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1713 // Negotiate and NTLM are often requested together. We only support NTLM.
1714 MockRead("WWW-Authenticate: Negotiate\r\n"),
1715 MockRead("WWW-Authenticate: NTLM\r\n"),
1716 MockRead("Connection: close\r\n"),
1717 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361718 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241719 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421720 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241721 };
1722
1723 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221724 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241725 // request we should be issuing -- the final header line contains a Type
1726 // 1 message.
1727 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1728 "Host: 172.22.68.17\r\n"
1729 "Connection: keep-alive\r\n"
1730 "Authorization: NTLM "
1731 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1732
1733 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1734 // (the credentials for the origin server). The second request continues
1735 // on the same connection.
1736 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1737 "Host: 172.22.68.17\r\n"
1738 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291739 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1740 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1741 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1742 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1743 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241744 };
1745
1746 MockRead data_reads2[] = {
1747 // The origin server responds with a Type 2 message.
1748 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1749 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291750 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241751 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1752 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1753 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1754 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1755 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1756 "BtAAAAAAA=\r\n"),
1757 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361758 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241759 MockRead("You are not authorized to view this page\r\n"),
1760
1761 // Lastly we get the desired content.
1762 MockRead("HTTP/1.1 200 OK\r\n"),
1763 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1764 MockRead("Content-Length: 13\r\n\r\n"),
1765 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421766 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241767 };
1768
[email protected]31a2bfe2010-02-09 08:03:391769 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1770 data_writes1, arraysize(data_writes1));
1771 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1772 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591773 session_deps.socket_factory.AddSocketDataProvider(&data1);
1774 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241775
1776 TestCompletionCallback callback1;
1777
[email protected]684970b2009-08-14 04:54:461778 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421779 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241780
1781 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421782 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241783
[email protected]0757e7702009-03-27 04:00:221784 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1785 TestCompletionCallback callback2;
1786 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421787 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221788 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421789 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221790 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1791
[email protected]1c773ea12009-04-28 19:58:421792 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241793 EXPECT_FALSE(response == NULL);
1794
1795 // The password prompt info should have been set in response->auth_challenge.
1796 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1797
[email protected]71e4573a2009-05-21 22:03:001798 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241799 EXPECT_EQ(L"", response->auth_challenge->realm);
1800 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1801
[email protected]0757e7702009-03-27 04:00:221802 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241803
[email protected]0757e7702009-03-27 04:00:221804 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421805 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241806
[email protected]0757e7702009-03-27 04:00:221807 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421808 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241809
1810 response = trans->GetResponseInfo();
1811 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1812 EXPECT_EQ(13, response->headers->GetContentLength());
1813}
1814
[email protected]385a4672009-03-11 22:21:291815// Enter a wrong password, and then the correct one.
1816TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421817 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201818 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591819 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401820 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431821 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291822
[email protected]1c773ea12009-04-28 19:58:421823 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291824 request.method = "GET";
1825 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1826 request.load_flags = 0;
1827
1828 MockWrite data_writes1[] = {
1829 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1830 "Host: 172.22.68.17\r\n"
1831 "Connection: keep-alive\r\n\r\n"),
1832 };
1833
1834 MockRead data_reads1[] = {
1835 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1836 // Negotiate and NTLM are often requested together. We only support NTLM.
1837 MockRead("WWW-Authenticate: Negotiate\r\n"),
1838 MockRead("WWW-Authenticate: NTLM\r\n"),
1839 MockRead("Connection: close\r\n"),
1840 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361841 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291842 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421843 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291844 };
1845
1846 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221847 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291848 // request we should be issuing -- the final header line contains a Type
1849 // 1 message.
1850 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1851 "Host: 172.22.68.17\r\n"
1852 "Connection: keep-alive\r\n"
1853 "Authorization: NTLM "
1854 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1855
1856 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1857 // (the credentials for the origin server). The second request continues
1858 // on the same connection.
1859 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1860 "Host: 172.22.68.17\r\n"
1861 "Connection: keep-alive\r\n"
1862 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1863 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1864 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1865 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1866 "4Ww7b7E=\r\n\r\n"),
1867 };
1868
1869 MockRead data_reads2[] = {
1870 // The origin server responds with a Type 2 message.
1871 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1872 MockRead("WWW-Authenticate: NTLM "
1873 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1874 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1875 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1876 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1877 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1878 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1879 "BtAAAAAAA=\r\n"),
1880 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361881 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291882 MockRead("You are not authorized to view this page\r\n"),
1883
1884 // Wrong password.
1885 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1886 MockRead("WWW-Authenticate: Negotiate\r\n"),
1887 MockRead("WWW-Authenticate: NTLM\r\n"),
1888 MockRead("Connection: close\r\n"),
1889 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361890 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291891 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421892 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291893 };
1894
1895 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221896 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291897 // request we should be issuing -- the final header line contains a Type
1898 // 1 message.
1899 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1900 "Host: 172.22.68.17\r\n"
1901 "Connection: keep-alive\r\n"
1902 "Authorization: NTLM "
1903 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1904
1905 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1906 // (the credentials for the origin server). The second request continues
1907 // on the same connection.
1908 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1909 "Host: 172.22.68.17\r\n"
1910 "Connection: keep-alive\r\n"
1911 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1912 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1913 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1914 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1915 "+4MUm7c=\r\n\r\n"),
1916 };
1917
1918 MockRead data_reads3[] = {
1919 // The origin server responds with a Type 2 message.
1920 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1921 MockRead("WWW-Authenticate: NTLM "
1922 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1923 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1924 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1925 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1926 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1927 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1928 "BtAAAAAAA=\r\n"),
1929 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361930 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291931 MockRead("You are not authorized to view this page\r\n"),
1932
1933 // Lastly we get the desired content.
1934 MockRead("HTTP/1.1 200 OK\r\n"),
1935 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1936 MockRead("Content-Length: 13\r\n\r\n"),
1937 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421938 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291939 };
1940
[email protected]31a2bfe2010-02-09 08:03:391941 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1942 data_writes1, arraysize(data_writes1));
1943 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1944 data_writes2, arraysize(data_writes2));
1945 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1946 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591947 session_deps.socket_factory.AddSocketDataProvider(&data1);
1948 session_deps.socket_factory.AddSocketDataProvider(&data2);
1949 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:291950
1951 TestCompletionCallback callback1;
1952
[email protected]684970b2009-08-14 04:54:461953 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421954 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291955
1956 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421957 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291958
[email protected]0757e7702009-03-27 04:00:221959 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291960 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221961 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421962 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291963 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421964 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221965 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291966
[email protected]1c773ea12009-04-28 19:58:421967 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291968 EXPECT_FALSE(response == NULL);
1969
1970 // The password prompt info should have been set in response->auth_challenge.
1971 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1972
[email protected]71e4573a2009-05-21 22:03:001973 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291974 EXPECT_EQ(L"", response->auth_challenge->realm);
1975 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1976
1977 TestCompletionCallback callback3;
1978
[email protected]0757e7702009-03-27 04:00:221979 // Enter the wrong password.
1980 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421981 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291982
1983 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421984 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291985
[email protected]0757e7702009-03-27 04:00:221986 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1987 TestCompletionCallback callback4;
1988 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421989 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221990 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421991 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221992 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1993
1994 response = trans->GetResponseInfo();
1995 EXPECT_FALSE(response == NULL);
1996
1997 // The password prompt info should have been set in response->auth_challenge.
1998 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1999
[email protected]71e4573a2009-05-21 22:03:002000 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222001 EXPECT_EQ(L"", response->auth_challenge->realm);
2002 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2003
2004 TestCompletionCallback callback5;
2005
2006 // Now enter the right password.
2007 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422008 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222009
2010 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422011 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222012
[email protected]385a4672009-03-11 22:21:292013 response = trans->GetResponseInfo();
2014 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2015 EXPECT_EQ(13, response->headers->GetContentLength());
2016}
[email protected]ea9dc9a2009-09-05 00:43:322017#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292018
[email protected]4ddaf2502008-10-23 18:26:192019// Test reading a server response which has only headers, and no body.
2020// After some maximum number of bytes is consumed, the transaction should
2021// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2022TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592023 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402024 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432025 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192026
[email protected]1c773ea12009-04-28 19:58:422027 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192028 request.method = "GET";
2029 request.url = GURL("http://www.google.com/");
2030 request.load_flags = 0;
2031
[email protected]b75b7b2f2009-10-06 00:54:532032 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432033 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532034 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192035
2036 MockRead data_reads[] = {
2037 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432038 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192039 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422040 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192041 };
[email protected]31a2bfe2010-02-09 08:03:392042 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592043 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192044
2045 TestCompletionCallback callback;
2046
[email protected]684970b2009-08-14 04:54:462047 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422048 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192049
2050 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422051 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192052
[email protected]1c773ea12009-04-28 19:58:422053 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192054 EXPECT_TRUE(response == NULL);
2055}
[email protected]f4e426b2008-11-05 00:24:492056
2057// Make sure that we don't try to reuse a TCPClientSocket when failing to
2058// establish tunnel.
2059// http://code.google.com/p/chromium/issues/detail?id=3772
2060TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2061 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592062 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012063
[email protected]228ff742009-06-05 01:19:592064 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492065
[email protected]5695b8c2009-09-30 21:36:432066 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492067
[email protected]1c773ea12009-04-28 19:58:422068 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492069 request.method = "GET";
2070 request.url = GURL("https://www.google.com/");
2071 request.load_flags = 0;
2072
2073 // Since we have proxy, should try to establish tunnel.
2074 MockWrite data_writes1[] = {
2075 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452076 "Host: www.google.com\r\n"
2077 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492078 };
2079
[email protected]77848d12008-11-14 00:00:222080 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492081 // connection. Usually a proxy would return 501 (not implemented),
2082 // or 200 (tunnel established).
2083 MockRead data_reads1[] = {
2084 MockRead("HTTP/1.1 404 Not Found\r\n"),
2085 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422086 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492087 };
2088
[email protected]31a2bfe2010-02-09 08:03:392089 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2090 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592091 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492092
2093 TestCompletionCallback callback1;
2094
[email protected]684970b2009-08-14 04:54:462095 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422096 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492097
2098 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422099 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492100
[email protected]1c773ea12009-04-28 19:58:422101 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082102 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492103
[email protected]b4404c02009-04-10 16:38:522104 // Empty the current queue. This is necessary because idle sockets are
2105 // added to the connection pool asynchronously with a PostTask.
2106 MessageLoop::current()->RunAllPending();
2107
[email protected]f4e426b2008-11-05 00:24:492108 // We now check to make sure the TCPClientSocket was not added back to
2109 // the pool.
[email protected]a937a06d2009-08-19 21:19:242110 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492111 trans.reset();
[email protected]b4404c02009-04-10 16:38:522112 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492113 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242114 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492115}
[email protected]372d34a2008-11-05 21:30:512116
[email protected]1b157c02009-04-21 01:55:402117// Make sure that we recycle a socket after reading all of the response body.
2118TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592119 SessionDependencies session_deps;
2120 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402121
[email protected]5695b8c2009-09-30 21:36:432122 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402123
[email protected]1c773ea12009-04-28 19:58:422124 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402125 request.method = "GET";
2126 request.url = GURL("http://www.google.com/");
2127 request.load_flags = 0;
2128
2129 MockRead data_reads[] = {
2130 // A part of the response body is received with the response headers.
2131 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2132 // The rest of the response body is received in two parts.
2133 MockRead("lo"),
2134 MockRead(" world"),
2135 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422136 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402137 };
2138
[email protected]31a2bfe2010-02-09 08:03:392139 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592140 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402141
2142 TestCompletionCallback callback;
2143
[email protected]684970b2009-08-14 04:54:462144 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422145 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402146
2147 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422148 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402149
[email protected]1c773ea12009-04-28 19:58:422150 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402151 EXPECT_TRUE(response != NULL);
2152
2153 EXPECT_TRUE(response->headers != NULL);
2154 std::string status_line = response->headers->GetStatusLine();
2155 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2156
[email protected]a937a06d2009-08-19 21:19:242157 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402158
2159 std::string response_data;
2160 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422161 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402162 EXPECT_EQ("hello world", response_data);
2163
2164 // Empty the current queue. This is necessary because idle sockets are
2165 // added to the connection pool asynchronously with a PostTask.
2166 MessageLoop::current()->RunAllPending();
2167
2168 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242169 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402170}
2171
[email protected]b4404c02009-04-10 16:38:522172// Make sure that we recycle a socket after a zero-length response.
2173// http://crbug.com/9880
2174TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592175 SessionDependencies session_deps;
2176 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522177
[email protected]5695b8c2009-09-30 21:36:432178 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522179
[email protected]1c773ea12009-04-28 19:58:422180 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522181 request.method = "GET";
2182 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2183 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2184 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2185 "rt=prt.2642,ol.2649,xjs.2951");
2186 request.load_flags = 0;
2187
2188 MockRead data_reads[] = {
2189 MockRead("HTTP/1.1 204 No Content\r\n"
2190 "Content-Length: 0\r\n"
2191 "Content-Type: text/html\r\n\r\n"),
2192 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422193 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522194 };
2195
[email protected]31a2bfe2010-02-09 08:03:392196 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592197 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522198
2199 TestCompletionCallback callback;
2200
[email protected]684970b2009-08-14 04:54:462201 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422202 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522203
2204 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422205 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522206
[email protected]1c773ea12009-04-28 19:58:422207 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522208 EXPECT_TRUE(response != NULL);
2209
2210 EXPECT_TRUE(response->headers != NULL);
2211 std::string status_line = response->headers->GetStatusLine();
2212 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2213
[email protected]a937a06d2009-08-19 21:19:242214 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522215
2216 std::string response_data;
2217 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422218 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522219 EXPECT_EQ("", response_data);
2220
2221 // Empty the current queue. This is necessary because idle sockets are
2222 // added to the connection pool asynchronously with a PostTask.
2223 MessageLoop::current()->RunAllPending();
2224
2225 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242226 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522227}
2228
[email protected]372d34a2008-11-05 21:30:512229TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422230 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512231 // Transaction 1: a GET request that succeeds. The socket is recycled
2232 // after use.
2233 request[0].method = "GET";
2234 request[0].url = GURL("http://www.google.com/");
2235 request[0].load_flags = 0;
2236 // Transaction 2: a POST request. Reuses the socket kept alive from
2237 // transaction 1. The first attempts fails when writing the POST data.
2238 // This causes the transaction to retry with a new socket. The second
2239 // attempt succeeds.
2240 request[1].method = "POST";
2241 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422242 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512243 request[1].upload_data->AppendBytes("foo", 3);
2244 request[1].load_flags = 0;
2245
[email protected]228ff742009-06-05 01:19:592246 SessionDependencies session_deps;
2247 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512248
2249 // The first socket is used for transaction 1 and the first attempt of
2250 // transaction 2.
2251
2252 // The response of transaction 1.
2253 MockRead data_reads1[] = {
2254 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2255 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422256 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512257 };
2258 // The mock write results of transaction 1 and the first attempt of
2259 // transaction 2.
2260 MockWrite data_writes1[] = {
2261 MockWrite(false, 64), // GET
2262 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422263 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512264 };
[email protected]31a2bfe2010-02-09 08:03:392265 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2266 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512267
2268 // The second socket is used for the second attempt of transaction 2.
2269
2270 // The response of transaction 2.
2271 MockRead data_reads2[] = {
2272 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2273 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422274 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512275 };
2276 // The mock write results of the second attempt of transaction 2.
2277 MockWrite data_writes2[] = {
2278 MockWrite(false, 93), // POST
2279 MockWrite(false, 3), // POST data
2280 };
[email protected]31a2bfe2010-02-09 08:03:392281 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2282 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512283
[email protected]5ecc992a42009-11-11 01:41:592284 session_deps.socket_factory.AddSocketDataProvider(&data1);
2285 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512286
2287 const char* kExpectedResponseData[] = {
2288 "hello world", "welcome"
2289 };
2290
2291 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422292 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432293 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512294
2295 TestCompletionCallback callback;
2296
[email protected]684970b2009-08-14 04:54:462297 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422298 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512299
2300 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422301 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512302
[email protected]1c773ea12009-04-28 19:58:422303 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512304 EXPECT_TRUE(response != NULL);
2305
2306 EXPECT_TRUE(response->headers != NULL);
2307 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2308
2309 std::string response_data;
2310 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422311 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512312 EXPECT_EQ(kExpectedResponseData[i], response_data);
2313 }
2314}
[email protected]f9ee6b52008-11-08 06:46:232315
2316// Test the request-challenge-retry sequence for basic auth when there is
2317// an identity in the URL. The request should be sent as normal, but when
2318// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322319TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592320 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402321 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432322 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232323
[email protected]1c773ea12009-04-28 19:58:422324 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232325 request.method = "GET";
2326 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292327 request.url = GURL("http://foo:b@[email protected]/");
2328
2329 // The password contains an escaped character -- for this test to pass it
2330 // will need to be unescaped by HttpNetworkTransaction.
2331 EXPECT_EQ("b%40r", request.url.password());
2332
[email protected]ea9dc9a2009-09-05 00:43:322333 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232334
2335 MockWrite data_writes1[] = {
2336 MockWrite("GET / HTTP/1.1\r\n"
2337 "Host: www.google.com\r\n"
2338 "Connection: keep-alive\r\n\r\n"),
2339 };
2340
2341 MockRead data_reads1[] = {
2342 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2343 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2344 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422345 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232346 };
2347
2348 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322349 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232350 MockWrite data_writes2[] = {
2351 MockWrite("GET / HTTP/1.1\r\n"
2352 "Host: www.google.com\r\n"
2353 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292354 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232355 };
2356
2357 MockRead data_reads2[] = {
2358 MockRead("HTTP/1.0 200 OK\r\n"),
2359 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422360 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232361 };
2362
[email protected]31a2bfe2010-02-09 08:03:392363 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2364 data_writes1, arraysize(data_writes1));
2365 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2366 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592367 session_deps.socket_factory.AddSocketDataProvider(&data1);
2368 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232369
2370 TestCompletionCallback callback1;
2371
[email protected]684970b2009-08-14 04:54:462372 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422373 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232374
2375 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422376 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232377
[email protected]0757e7702009-03-27 04:00:222378 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2379 TestCompletionCallback callback2;
2380 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422381 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222382 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422383 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222384 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2385
[email protected]1c773ea12009-04-28 19:58:422386 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232387 EXPECT_FALSE(response == NULL);
2388
2389 // There is no challenge info, since the identity in URL worked.
2390 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2391
2392 EXPECT_EQ(100, response->headers->GetContentLength());
2393
2394 // Empty the current queue.
2395 MessageLoop::current()->RunAllPending();
2396}
2397
[email protected]ea9dc9a2009-09-05 00:43:322398// Test the request-challenge-retry sequence for basic auth when there is
2399// an incorrect identity in the URL. The identity from the URL should be used
2400// only once.
2401TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2402 SessionDependencies session_deps;
2403 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432404 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322405
2406 HttpRequestInfo request;
2407 request.method = "GET";
2408 // Note: the URL has a username:password in it. The password "baz" is
2409 // wrong (should be "bar").
2410 request.url = GURL("http://foo:[email protected]/");
2411
2412 request.load_flags = LOAD_NORMAL;
2413
2414 MockWrite data_writes1[] = {
2415 MockWrite("GET / HTTP/1.1\r\n"
2416 "Host: www.google.com\r\n"
2417 "Connection: keep-alive\r\n\r\n"),
2418 };
2419
2420 MockRead data_reads1[] = {
2421 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2422 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2423 MockRead("Content-Length: 10\r\n\r\n"),
2424 MockRead(false, ERR_FAILED),
2425 };
2426
2427 // After the challenge above, the transaction will be restarted using the
2428 // identity from the url (foo, baz) to answer the challenge.
2429 MockWrite data_writes2[] = {
2430 MockWrite("GET / HTTP/1.1\r\n"
2431 "Host: www.google.com\r\n"
2432 "Connection: keep-alive\r\n"
2433 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2434 };
2435
2436 MockRead data_reads2[] = {
2437 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2438 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2439 MockRead("Content-Length: 10\r\n\r\n"),
2440 MockRead(false, ERR_FAILED),
2441 };
2442
2443 // After the challenge above, the transaction will be restarted using the
2444 // identity supplied by the user (foo, bar) to answer the challenge.
2445 MockWrite data_writes3[] = {
2446 MockWrite("GET / HTTP/1.1\r\n"
2447 "Host: www.google.com\r\n"
2448 "Connection: keep-alive\r\n"
2449 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2450 };
2451
2452 MockRead data_reads3[] = {
2453 MockRead("HTTP/1.0 200 OK\r\n"),
2454 MockRead("Content-Length: 100\r\n\r\n"),
2455 MockRead(false, OK),
2456 };
2457
[email protected]31a2bfe2010-02-09 08:03:392458 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2459 data_writes1, arraysize(data_writes1));
2460 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2461 data_writes2, arraysize(data_writes2));
2462 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2463 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592464 session_deps.socket_factory.AddSocketDataProvider(&data1);
2465 session_deps.socket_factory.AddSocketDataProvider(&data2);
2466 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322467
2468 TestCompletionCallback callback1;
2469
2470 int rv = trans->Start(&request, &callback1, NULL);
2471 EXPECT_EQ(ERR_IO_PENDING, rv);
2472
2473 rv = callback1.WaitForResult();
2474 EXPECT_EQ(OK, rv);
2475
2476 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2477 TestCompletionCallback callback2;
2478 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2479 EXPECT_EQ(ERR_IO_PENDING, rv);
2480 rv = callback2.WaitForResult();
2481 EXPECT_EQ(OK, rv);
2482 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2483
2484 const HttpResponseInfo* response = trans->GetResponseInfo();
2485 EXPECT_FALSE(response == NULL);
2486 // The password prompt info should have been set in response->auth_challenge.
2487 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2488
2489 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2490 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2491 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2492
2493 TestCompletionCallback callback3;
2494 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2495 EXPECT_EQ(ERR_IO_PENDING, rv);
2496 rv = callback3.WaitForResult();
2497 EXPECT_EQ(OK, rv);
2498 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2499
2500 response = trans->GetResponseInfo();
2501 EXPECT_FALSE(response == NULL);
2502
2503 // There is no challenge info, since the identity worked.
2504 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2505
2506 EXPECT_EQ(100, response->headers->GetContentLength());
2507
2508 // Empty the current queue.
2509 MessageLoop::current()->RunAllPending();
2510}
2511
[email protected]f9ee6b52008-11-08 06:46:232512// Test that previously tried username/passwords for a realm get re-used.
2513TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592514 SessionDependencies session_deps;
2515 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232516
2517 // Transaction 1: authenticate (foo, bar) on MyRealm1
2518 {
[email protected]5695b8c2009-09-30 21:36:432519 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232520
[email protected]1c773ea12009-04-28 19:58:422521 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232522 request.method = "GET";
2523 request.url = GURL("http://www.google.com/x/y/z");
2524 request.load_flags = 0;
2525
2526 MockWrite data_writes1[] = {
2527 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2528 "Host: www.google.com\r\n"
2529 "Connection: keep-alive\r\n\r\n"),
2530 };
2531
2532 MockRead data_reads1[] = {
2533 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2534 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2535 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422536 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232537 };
2538
2539 // Resend with authorization (username=foo, password=bar)
2540 MockWrite data_writes2[] = {
2541 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2542 "Host: www.google.com\r\n"
2543 "Connection: keep-alive\r\n"
2544 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2545 };
2546
2547 // Sever accepts the authorization.
2548 MockRead data_reads2[] = {
2549 MockRead("HTTP/1.0 200 OK\r\n"),
2550 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422551 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232552 };
2553
[email protected]31a2bfe2010-02-09 08:03:392554 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2555 data_writes1, arraysize(data_writes1));
2556 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2557 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592558 session_deps.socket_factory.AddSocketDataProvider(&data1);
2559 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232560
2561 TestCompletionCallback callback1;
2562
[email protected]684970b2009-08-14 04:54:462563 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422564 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232565
2566 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422567 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232568
[email protected]1c773ea12009-04-28 19:58:422569 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232570 EXPECT_FALSE(response == NULL);
2571
2572 // The password prompt info should have been set in
2573 // response->auth_challenge.
2574 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2575
[email protected]71e4573a2009-05-21 22:03:002576 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232577 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2578 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2579
2580 TestCompletionCallback callback2;
2581
2582 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422583 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232584
2585 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422586 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232587
2588 response = trans->GetResponseInfo();
2589 EXPECT_FALSE(response == NULL);
2590 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2591 EXPECT_EQ(100, response->headers->GetContentLength());
2592 }
2593
2594 // ------------------------------------------------------------------------
2595
2596 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2597 {
[email protected]5695b8c2009-09-30 21:36:432598 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232599
[email protected]1c773ea12009-04-28 19:58:422600 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232601 request.method = "GET";
2602 // Note that Transaction 1 was at /x/y/z, so this is in the same
2603 // protection space as MyRealm1.
2604 request.url = GURL("http://www.google.com/x/y/a/b");
2605 request.load_flags = 0;
2606
2607 MockWrite data_writes1[] = {
2608 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2609 "Host: www.google.com\r\n"
2610 "Connection: keep-alive\r\n"
2611 // Send preemptive authorization for MyRealm1
2612 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2613 };
2614
2615 // The server didn't like the preemptive authorization, and
2616 // challenges us for a different realm (MyRealm2).
2617 MockRead data_reads1[] = {
2618 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2619 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2620 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422621 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232622 };
2623
2624 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2625 MockWrite data_writes2[] = {
2626 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2627 "Host: www.google.com\r\n"
2628 "Connection: keep-alive\r\n"
2629 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2630 };
2631
2632 // Sever accepts the authorization.
2633 MockRead data_reads2[] = {
2634 MockRead("HTTP/1.0 200 OK\r\n"),
2635 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422636 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232637 };
2638
[email protected]31a2bfe2010-02-09 08:03:392639 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2640 data_writes1, arraysize(data_writes1));
2641 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2642 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592643 session_deps.socket_factory.AddSocketDataProvider(&data1);
2644 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232645
2646 TestCompletionCallback callback1;
2647
[email protected]684970b2009-08-14 04:54:462648 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422649 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232650
2651 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422652 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232653
[email protected]1c773ea12009-04-28 19:58:422654 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232655 EXPECT_FALSE(response == NULL);
2656
2657 // The password prompt info should have been set in
2658 // response->auth_challenge.
2659 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2660
[email protected]71e4573a2009-05-21 22:03:002661 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232662 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2663 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2664
2665 TestCompletionCallback callback2;
2666
2667 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422668 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232669
2670 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422671 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232672
2673 response = trans->GetResponseInfo();
2674 EXPECT_FALSE(response == NULL);
2675 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2676 EXPECT_EQ(100, response->headers->GetContentLength());
2677 }
2678
2679 // ------------------------------------------------------------------------
2680
2681 // Transaction 3: Resend a request in MyRealm's protection space --
2682 // succeed with preemptive authorization.
2683 {
[email protected]5695b8c2009-09-30 21:36:432684 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232685
[email protected]1c773ea12009-04-28 19:58:422686 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232687 request.method = "GET";
2688 request.url = GURL("http://www.google.com/x/y/z2");
2689 request.load_flags = 0;
2690
2691 MockWrite data_writes1[] = {
2692 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2693 "Host: www.google.com\r\n"
2694 "Connection: keep-alive\r\n"
2695 // The authorization for MyRealm1 gets sent preemptively
2696 // (since the url is in the same protection space)
2697 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2698 };
2699
2700 // Sever accepts the preemptive authorization
2701 MockRead data_reads1[] = {
2702 MockRead("HTTP/1.0 200 OK\r\n"),
2703 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422704 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232705 };
2706
[email protected]31a2bfe2010-02-09 08:03:392707 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2708 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592709 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232710
2711 TestCompletionCallback callback1;
2712
[email protected]684970b2009-08-14 04:54:462713 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422714 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232715
2716 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422717 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232718
[email protected]1c773ea12009-04-28 19:58:422719 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232720 EXPECT_FALSE(response == NULL);
2721
2722 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2723 EXPECT_EQ(100, response->headers->GetContentLength());
2724 }
2725
2726 // ------------------------------------------------------------------------
2727
2728 // Transaction 4: request another URL in MyRealm (however the
2729 // url is not known to belong to the protection space, so no pre-auth).
2730 {
[email protected]5695b8c2009-09-30 21:36:432731 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232732
[email protected]1c773ea12009-04-28 19:58:422733 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232734 request.method = "GET";
2735 request.url = GURL("http://www.google.com/x/1");
2736 request.load_flags = 0;
2737
2738 MockWrite data_writes1[] = {
2739 MockWrite("GET /x/1 HTTP/1.1\r\n"
2740 "Host: www.google.com\r\n"
2741 "Connection: keep-alive\r\n\r\n"),
2742 };
2743
2744 MockRead data_reads1[] = {
2745 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2746 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2747 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422748 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232749 };
2750
2751 // Resend with authorization from MyRealm's cache.
2752 MockWrite data_writes2[] = {
2753 MockWrite("GET /x/1 HTTP/1.1\r\n"
2754 "Host: www.google.com\r\n"
2755 "Connection: keep-alive\r\n"
2756 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2757 };
2758
2759 // Sever accepts the authorization.
2760 MockRead data_reads2[] = {
2761 MockRead("HTTP/1.0 200 OK\r\n"),
2762 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422763 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232764 };
2765
[email protected]31a2bfe2010-02-09 08:03:392766 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2767 data_writes1, arraysize(data_writes1));
2768 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2769 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592770 session_deps.socket_factory.AddSocketDataProvider(&data1);
2771 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232772
2773 TestCompletionCallback callback1;
2774
[email protected]684970b2009-08-14 04:54:462775 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422776 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232777
2778 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422779 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232780
[email protected]0757e7702009-03-27 04:00:222781 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2782 TestCompletionCallback callback2;
2783 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422784 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222785 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422786 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222787 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2788
[email protected]1c773ea12009-04-28 19:58:422789 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232790 EXPECT_FALSE(response == NULL);
2791 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2792 EXPECT_EQ(100, response->headers->GetContentLength());
2793 }
2794
2795 // ------------------------------------------------------------------------
2796
2797 // Transaction 5: request a URL in MyRealm, but the server rejects the
2798 // cached identity. Should invalidate and re-prompt.
2799 {
[email protected]5695b8c2009-09-30 21:36:432800 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232801
[email protected]1c773ea12009-04-28 19:58:422802 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232803 request.method = "GET";
2804 request.url = GURL("http://www.google.com/p/q/t");
2805 request.load_flags = 0;
2806
2807 MockWrite data_writes1[] = {
2808 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2809 "Host: www.google.com\r\n"
2810 "Connection: keep-alive\r\n\r\n"),
2811 };
2812
2813 MockRead data_reads1[] = {
2814 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2815 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2816 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422817 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232818 };
2819
2820 // Resend with authorization from cache for MyRealm.
2821 MockWrite data_writes2[] = {
2822 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2823 "Host: www.google.com\r\n"
2824 "Connection: keep-alive\r\n"
2825 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2826 };
2827
2828 // Sever rejects the authorization.
2829 MockRead data_reads2[] = {
2830 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2831 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2832 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422833 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232834 };
2835
2836 // At this point we should prompt for new credentials for MyRealm.
2837 // Restart with username=foo3, password=foo4.
2838 MockWrite data_writes3[] = {
2839 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2840 "Host: www.google.com\r\n"
2841 "Connection: keep-alive\r\n"
2842 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2843 };
2844
2845 // Sever accepts the authorization.
2846 MockRead data_reads3[] = {
2847 MockRead("HTTP/1.0 200 OK\r\n"),
2848 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422849 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232850 };
2851
[email protected]31a2bfe2010-02-09 08:03:392852 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2853 data_writes1, arraysize(data_writes1));
2854 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2855 data_writes2, arraysize(data_writes2));
2856 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2857 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592858 session_deps.socket_factory.AddSocketDataProvider(&data1);
2859 session_deps.socket_factory.AddSocketDataProvider(&data2);
2860 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232861
2862 TestCompletionCallback callback1;
2863
[email protected]684970b2009-08-14 04:54:462864 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422865 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232866
2867 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422868 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232869
[email protected]0757e7702009-03-27 04:00:222870 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2871 TestCompletionCallback callback2;
2872 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422873 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222874 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422875 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222876 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2877
[email protected]1c773ea12009-04-28 19:58:422878 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232879 EXPECT_FALSE(response == NULL);
2880
2881 // The password prompt info should have been set in
2882 // response->auth_challenge.
2883 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2884
[email protected]71e4573a2009-05-21 22:03:002885 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232886 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2887 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2888
[email protected]0757e7702009-03-27 04:00:222889 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232890
[email protected]0757e7702009-03-27 04:00:222891 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422892 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232893
[email protected]0757e7702009-03-27 04:00:222894 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422895 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232896
2897 response = trans->GetResponseInfo();
2898 EXPECT_FALSE(response == NULL);
2899 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2900 EXPECT_EQ(100, response->headers->GetContentLength());
2901 }
2902}
[email protected]89ceba9a2009-03-21 03:46:062903
2904// Test the ResetStateForRestart() private method.
2905TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2906 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592907 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402908 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432909 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062910
2911 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062912 trans->read_buf_ = new IOBuffer(15);
2913 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572914 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062915
2916 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:142917 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:572918 response->auth_challenge = new AuthChallengeInfo();
2919 response->ssl_info.cert_status = -15;
2920 response->response_time = base::Time::Now();
2921 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062922
2923 { // Setup state for response_.vary_data
2924 HttpRequestInfo request;
2925 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2926 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:572927 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]89ceba9a2009-03-21 03:46:062928 request.extra_headers = "Foo: 1\nbar: 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/");
3087 request.user_agent = "Chromium Ultra Awesome X Edition";
3088
3089 MockWrite data_writes[] = {
3090 MockWrite("GET / HTTP/1.1\r\n"
3091 "Host: www.google.com\r\n"
3092 "Connection: keep-alive\r\n"
3093 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3094 };
3095
3096 // Lastly, the server responds with the actual content.
3097 MockRead data_reads[] = {
3098 MockRead("HTTP/1.0 200 OK\r\n"),
3099 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3100 MockRead("Content-Length: 100\r\n\r\n"),
3101 MockRead(false, OK),
3102 };
3103
[email protected]31a2bfe2010-02-09 08:03:393104 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3105 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593106 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423107
3108 TestCompletionCallback callback;
3109
[email protected]684970b2009-08-14 04:54:463110 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423111 EXPECT_EQ(ERR_IO_PENDING, rv);
3112
3113 rv = callback.WaitForResult();
3114 EXPECT_EQ(OK, rv);
3115}
3116
3117TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593118 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403119 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433120 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423121
3122 HttpRequestInfo request;
3123 request.method = "GET";
3124 request.url = GURL("http://www.google.com/");
3125 request.load_flags = 0;
3126 request.referrer = GURL("http://the.previous.site.com/");
3127
3128 MockWrite data_writes[] = {
3129 MockWrite("GET / HTTP/1.1\r\n"
3130 "Host: www.google.com\r\n"
3131 "Connection: keep-alive\r\n"
3132 "Referer: http://the.previous.site.com/\r\n\r\n"),
3133 };
3134
3135 // Lastly, the server responds with the actual content.
3136 MockRead data_reads[] = {
3137 MockRead("HTTP/1.0 200 OK\r\n"),
3138 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3139 MockRead("Content-Length: 100\r\n\r\n"),
3140 MockRead(false, OK),
3141 };
3142
[email protected]31a2bfe2010-02-09 08:03:393143 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3144 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593145 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423146
3147 TestCompletionCallback callback;
3148
[email protected]684970b2009-08-14 04:54:463149 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423150 EXPECT_EQ(ERR_IO_PENDING, rv);
3151
3152 rv = callback.WaitForResult();
3153 EXPECT_EQ(OK, rv);
3154}
3155
3156TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593157 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403158 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433159 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423160
3161 HttpRequestInfo request;
3162 request.method = "POST";
3163 request.url = GURL("http://www.google.com/");
3164
3165 MockWrite data_writes[] = {
3166 MockWrite("POST / HTTP/1.1\r\n"
3167 "Host: www.google.com\r\n"
3168 "Connection: keep-alive\r\n"
3169 "Content-Length: 0\r\n\r\n"),
3170 };
3171
3172 // Lastly, the server responds with the actual content.
3173 MockRead data_reads[] = {
3174 MockRead("HTTP/1.0 200 OK\r\n"),
3175 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3176 MockRead("Content-Length: 100\r\n\r\n"),
3177 MockRead(false, OK),
3178 };
3179
[email protected]31a2bfe2010-02-09 08:03:393180 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3181 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593182 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423183
3184 TestCompletionCallback callback;
3185
[email protected]684970b2009-08-14 04:54:463186 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423187 EXPECT_EQ(ERR_IO_PENDING, rv);
3188
3189 rv = callback.WaitForResult();
3190 EXPECT_EQ(OK, rv);
3191}
3192
3193TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593194 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403195 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433196 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423197
3198 HttpRequestInfo request;
3199 request.method = "PUT";
3200 request.url = GURL("http://www.google.com/");
3201
3202 MockWrite data_writes[] = {
3203 MockWrite("PUT / HTTP/1.1\r\n"
3204 "Host: www.google.com\r\n"
3205 "Connection: keep-alive\r\n"
3206 "Content-Length: 0\r\n\r\n"),
3207 };
3208
3209 // Lastly, the server responds with the actual content.
3210 MockRead data_reads[] = {
3211 MockRead("HTTP/1.0 200 OK\r\n"),
3212 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3213 MockRead("Content-Length: 100\r\n\r\n"),
3214 MockRead(false, OK),
3215 };
3216
[email protected]31a2bfe2010-02-09 08:03:393217 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3218 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593219 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423220
3221 TestCompletionCallback callback;
3222
[email protected]684970b2009-08-14 04:54:463223 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423224 EXPECT_EQ(ERR_IO_PENDING, rv);
3225
3226 rv = callback.WaitForResult();
3227 EXPECT_EQ(OK, rv);
3228}
3229
3230TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593231 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403232 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433233 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423234
3235 HttpRequestInfo request;
3236 request.method = "HEAD";
3237 request.url = GURL("http://www.google.com/");
3238
3239 MockWrite data_writes[] = {
3240 MockWrite("HEAD / HTTP/1.1\r\n"
3241 "Host: www.google.com\r\n"
3242 "Connection: keep-alive\r\n"
3243 "Content-Length: 0\r\n\r\n"),
3244 };
3245
3246 // Lastly, the server responds with the actual content.
3247 MockRead data_reads[] = {
3248 MockRead("HTTP/1.0 200 OK\r\n"),
3249 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3250 MockRead("Content-Length: 100\r\n\r\n"),
3251 MockRead(false, OK),
3252 };
3253
[email protected]31a2bfe2010-02-09 08:03:393254 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3255 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593256 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423257
3258 TestCompletionCallback callback;
3259
[email protected]684970b2009-08-14 04:54:463260 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423261 EXPECT_EQ(ERR_IO_PENDING, rv);
3262
3263 rv = callback.WaitForResult();
3264 EXPECT_EQ(OK, rv);
3265}
3266
3267TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593268 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403269 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433270 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423271
3272 HttpRequestInfo request;
3273 request.method = "GET";
3274 request.url = GURL("http://www.google.com/");
3275 request.load_flags = LOAD_BYPASS_CACHE;
3276
3277 MockWrite data_writes[] = {
3278 MockWrite("GET / HTTP/1.1\r\n"
3279 "Host: www.google.com\r\n"
3280 "Connection: keep-alive\r\n"
3281 "Pragma: no-cache\r\n"
3282 "Cache-Control: no-cache\r\n\r\n"),
3283 };
3284
3285 // Lastly, the server responds with the actual content.
3286 MockRead data_reads[] = {
3287 MockRead("HTTP/1.0 200 OK\r\n"),
3288 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3289 MockRead("Content-Length: 100\r\n\r\n"),
3290 MockRead(false, OK),
3291 };
3292
[email protected]31a2bfe2010-02-09 08:03:393293 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3294 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593295 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423296
3297 TestCompletionCallback callback;
3298
[email protected]684970b2009-08-14 04:54:463299 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423300 EXPECT_EQ(ERR_IO_PENDING, rv);
3301
3302 rv = callback.WaitForResult();
3303 EXPECT_EQ(OK, rv);
3304}
3305
3306TEST_F(HttpNetworkTransactionTest,
3307 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593308 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403309 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433310 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423311
3312 HttpRequestInfo request;
3313 request.method = "GET";
3314 request.url = GURL("http://www.google.com/");
3315 request.load_flags = LOAD_VALIDATE_CACHE;
3316
3317 MockWrite data_writes[] = {
3318 MockWrite("GET / HTTP/1.1\r\n"
3319 "Host: www.google.com\r\n"
3320 "Connection: keep-alive\r\n"
3321 "Cache-Control: max-age=0\r\n\r\n"),
3322 };
3323
3324 // Lastly, the server responds with the actual content.
3325 MockRead data_reads[] = {
3326 MockRead("HTTP/1.0 200 OK\r\n"),
3327 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3328 MockRead("Content-Length: 100\r\n\r\n"),
3329 MockRead(false, OK),
3330 };
3331
[email protected]31a2bfe2010-02-09 08:03:393332 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3333 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593334 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423335
3336 TestCompletionCallback callback;
3337
[email protected]684970b2009-08-14 04:54:463338 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423339 EXPECT_EQ(ERR_IO_PENDING, rv);
3340
3341 rv = callback.WaitForResult();
3342 EXPECT_EQ(OK, rv);
3343}
3344
3345TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593346 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403347 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433348 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423349
3350 HttpRequestInfo request;
3351 request.method = "GET";
3352 request.url = GURL("http://www.google.com/");
3353 request.extra_headers = "FooHeader: Bar\r\n";
3354
3355 MockWrite data_writes[] = {
3356 MockWrite("GET / HTTP/1.1\r\n"
3357 "Host: www.google.com\r\n"
3358 "Connection: keep-alive\r\n"
3359 "FooHeader: Bar\r\n\r\n"),
3360 };
3361
3362 // Lastly, the server responds with the actual content.
3363 MockRead data_reads[] = {
3364 MockRead("HTTP/1.0 200 OK\r\n"),
3365 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3366 MockRead("Content-Length: 100\r\n\r\n"),
3367 MockRead(false, OK),
3368 };
3369
[email protected]31a2bfe2010-02-09 08:03:393370 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3371 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593372 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423373
3374 TestCompletionCallback callback;
3375
[email protected]684970b2009-08-14 04:54:463376 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423377 EXPECT_EQ(ERR_IO_PENDING, rv);
3378
3379 rv = callback.WaitForResult();
3380 EXPECT_EQ(OK, rv);
3381}
3382
[email protected]3cd17242009-06-23 02:59:023383TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093384 SessionDependencies session_deps(
3385 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023386
3387 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433388 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023389
3390 HttpRequestInfo request;
3391 request.method = "GET";
3392 request.url = GURL("http://www.google.com/");
3393 request.load_flags = 0;
3394
3395 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3396 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3397
3398 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353399 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023400 MockWrite("GET / HTTP/1.1\r\n"
3401 "Host: www.google.com\r\n"
3402 "Connection: keep-alive\r\n\r\n")
3403 };
3404
3405 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593406 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023407 MockRead("HTTP/1.0 200 OK\r\n"),
3408 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3409 MockRead("Payload"),
3410 MockRead(false, OK)
3411 };
3412
[email protected]31a2bfe2010-02-09 08:03:393413 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3414 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593415 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023416
3417 TestCompletionCallback callback;
3418
[email protected]684970b2009-08-14 04:54:463419 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023420 EXPECT_EQ(ERR_IO_PENDING, rv);
3421
3422 rv = callback.WaitForResult();
3423 EXPECT_EQ(OK, rv);
3424
3425 const HttpResponseInfo* response = trans->GetResponseInfo();
3426 EXPECT_FALSE(response == NULL);
3427
3428 std::string response_text;
3429 rv = ReadTransaction(trans.get(), &response_text);
3430 EXPECT_EQ(OK, rv);
3431 EXPECT_EQ("Payload", response_text);
3432}
3433
3434TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093435 SessionDependencies session_deps(
3436 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023437
3438 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433439 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023440
3441 HttpRequestInfo request;
3442 request.method = "GET";
3443 request.url = GURL("https://www.google.com/");
3444 request.load_flags = 0;
3445
3446 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3447 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3448
3449 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353450 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3451 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023452 MockWrite("GET / HTTP/1.1\r\n"
3453 "Host: www.google.com\r\n"
3454 "Connection: keep-alive\r\n\r\n")
3455 };
3456
3457 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353458 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3459 arraysize(read_buffer)),
3460 MockRead("HTTP/1.0 200 OK\r\n"),
3461 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3462 MockRead("Payload"),
3463 MockRead(false, OK)
3464 };
3465
[email protected]31a2bfe2010-02-09 08:03:393466 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3467 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593468 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353469
[email protected]5ecc992a42009-11-11 01:41:593470 SSLSocketDataProvider ssl(true, OK);
3471 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353472
3473 TestCompletionCallback callback;
3474
[email protected]684970b2009-08-14 04:54:463475 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353476 EXPECT_EQ(ERR_IO_PENDING, rv);
3477
3478 rv = callback.WaitForResult();
3479 EXPECT_EQ(OK, rv);
3480
3481 const HttpResponseInfo* response = trans->GetResponseInfo();
3482 EXPECT_FALSE(response == NULL);
3483
3484 std::string response_text;
3485 rv = ReadTransaction(trans.get(), &response_text);
3486 EXPECT_EQ(OK, rv);
3487 EXPECT_EQ("Payload", response_text);
3488}
3489
3490TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093491 SessionDependencies session_deps(
3492 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353493
3494 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433495 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353496
3497 HttpRequestInfo request;
3498 request.method = "GET";
3499 request.url = GURL("http://www.google.com/");
3500 request.load_flags = 0;
3501
3502 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3503 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373504 const char kSOCKS5OkRequest[] = {
3505 0x05, // Version
3506 0x01, // Command (CONNECT)
3507 0x00, // Reserved.
3508 0x03, // Address type (DOMAINNAME).
3509 0x0E, // Length of domain (14)
3510 // Domain string:
3511 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3512 0x00, 0x50, // 16-bit port (80)
3513 };
[email protected]e0c27be2009-07-15 13:09:353514 const char kSOCKS5OkResponse[] =
3515 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3516
3517 MockWrite data_writes[] = {
3518 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3519 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3520 MockWrite("GET / HTTP/1.1\r\n"
3521 "Host: www.google.com\r\n"
3522 "Connection: keep-alive\r\n\r\n")
3523 };
3524
3525 MockRead data_reads[] = {
3526 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3527 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3528 MockRead("HTTP/1.0 200 OK\r\n"),
3529 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3530 MockRead("Payload"),
3531 MockRead(false, OK)
3532 };
3533
[email protected]31a2bfe2010-02-09 08:03:393534 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3535 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593536 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353537
3538 TestCompletionCallback callback;
3539
[email protected]684970b2009-08-14 04:54:463540 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353541 EXPECT_EQ(ERR_IO_PENDING, rv);
3542
3543 rv = callback.WaitForResult();
3544 EXPECT_EQ(OK, rv);
3545
3546 const HttpResponseInfo* response = trans->GetResponseInfo();
3547 EXPECT_FALSE(response == NULL);
3548
3549 std::string response_text;
3550 rv = ReadTransaction(trans.get(), &response_text);
3551 EXPECT_EQ(OK, rv);
3552 EXPECT_EQ("Payload", response_text);
3553}
3554
3555TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093556 SessionDependencies session_deps(
3557 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353558
3559 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433560 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353561
3562 HttpRequestInfo request;
3563 request.method = "GET";
3564 request.url = GURL("https://www.google.com/");
3565 request.load_flags = 0;
3566
3567 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3568 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373569 const unsigned char kSOCKS5OkRequest[] = {
3570 0x05, // Version
3571 0x01, // Command (CONNECT)
3572 0x00, // Reserved.
3573 0x03, // Address type (DOMAINNAME).
3574 0x0E, // Length of domain (14)
3575 // Domain string:
3576 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3577 0x01, 0xBB, // 16-bit port (443)
3578 };
3579
[email protected]e0c27be2009-07-15 13:09:353580 const char kSOCKS5OkResponse[] =
3581 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3582
3583 MockWrite data_writes[] = {
3584 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3585 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3586 arraysize(kSOCKS5OkRequest)),
3587 MockWrite("GET / HTTP/1.1\r\n"
3588 "Host: www.google.com\r\n"
3589 "Connection: keep-alive\r\n\r\n")
3590 };
3591
3592 MockRead data_reads[] = {
3593 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3594 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023595 MockRead("HTTP/1.0 200 OK\r\n"),
3596 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3597 MockRead("Payload"),
3598 MockRead(false, OK)
3599 };
3600
[email protected]31a2bfe2010-02-09 08:03:393601 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3602 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593603 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023604
[email protected]5ecc992a42009-11-11 01:41:593605 SSLSocketDataProvider ssl(true, OK);
3606 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023607
3608 TestCompletionCallback callback;
3609
[email protected]684970b2009-08-14 04:54:463610 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023611 EXPECT_EQ(ERR_IO_PENDING, rv);
3612
3613 rv = callback.WaitForResult();
3614 EXPECT_EQ(OK, rv);
3615
3616 const HttpResponseInfo* response = trans->GetResponseInfo();
3617 EXPECT_FALSE(response == NULL);
3618
3619 std::string response_text;
3620 rv = ReadTransaction(trans.get(), &response_text);
3621 EXPECT_EQ(OK, rv);
3622 EXPECT_EQ("Payload", response_text);
3623}
3624
[email protected]04e5be32009-06-26 20:00:313625// Tests that for connection endpoints the group names are correctly set.
3626TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3627 const struct {
3628 const std::string proxy_server;
3629 const std::string url;
3630 const std::string expected_group_name;
3631 } tests[] = {
3632 {
3633 "", // no proxy (direct)
3634 "http://www.google.com/direct",
3635 "http://www.google.com/",
3636 },
3637 {
3638 "http_proxy",
3639 "http://www.google.com/http_proxy_normal",
3640 "proxy/http_proxy:80/",
3641 },
3642 {
3643 "socks4://socks_proxy:1080",
3644 "http://www.google.com/socks4_direct",
3645 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3646 },
3647
3648 // SSL Tests
3649 {
3650 "",
3651 "https://www.google.com/direct_ssl",
3652 "https://www.google.com/",
3653 },
3654 {
3655 "http_proxy",
3656 "https://www.google.com/http_connect_ssl",
3657 "proxy/http_proxy:80/https://www.google.com/",
3658 },
3659 {
3660 "socks4://socks_proxy:1080",
3661 "https://www.google.com/socks4_ssl",
3662 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3663 },
3664 };
3665
3666 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093667 SessionDependencies session_deps(
3668 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313669
[email protected]04e5be32009-06-26 20:00:313670 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a796bcec2010-03-22 17:17:263671
3672 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
3673 new CaptureGroupNameTCPSocketPool(session.get(),
3674 session->socket_factory()));
3675 session->tcp_socket_pool_ = tcp_conn_pool.get();
3676 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
3677 new CaptureGroupNameSOCKSSocketPool(session.get(),
3678 tcp_conn_pool.get()));
3679 session->socks_socket_pool_ = socks_conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313680
[email protected]5695b8c2009-09-30 21:36:433681 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313682
3683 HttpRequestInfo request;
3684 request.method = "GET";
3685 request.url = GURL(tests[i].url);
3686 request.load_flags = 0;
3687
3688 TestCompletionCallback callback;
3689
3690 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463691 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]a796bcec2010-03-22 17:17:263692 std::string allgroups = tcp_conn_pool->last_group_name_received() +
3693 socks_conn_pool->last_group_name_received();
3694 EXPECT_EQ(tests[i].expected_group_name, allgroups);
[email protected]04e5be32009-06-26 20:00:313695 }
3696}
3697
[email protected]9172a982009-06-06 00:30:253698TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543699 SessionDependencies session_deps(
3700 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323701
[email protected]69719062010-01-05 20:09:213702 // This simulates failure resolving all hostnames; that means we will fail
3703 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:323704 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3705
[email protected]9172a982009-06-06 00:30:253706 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433707 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253708
3709 HttpRequestInfo request;
3710 request.method = "GET";
3711 request.url = GURL("http://www.google.com/");
3712
3713 TestCompletionCallback callback;
3714
[email protected]684970b2009-08-14 04:54:463715 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253716 EXPECT_EQ(ERR_IO_PENDING, rv);
3717
[email protected]9172a982009-06-06 00:30:253718 rv = callback.WaitForResult();
3719 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3720}
3721
[email protected]f3e6c1e2009-06-15 20:52:123722// Host resolution observer used by
3723// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3724// resovle requests are issued with a referrer of |expected_referrer|.
3725class ResolutionReferrerObserver : public HostResolver::Observer {
3726 public:
3727 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3728 : expected_referrer_(expected_referrer),
3729 called_start_with_referrer_(false),
3730 called_finish_with_referrer_(false) {
3731 }
3732
3733 virtual void OnStartResolution(int id,
3734 const HostResolver::RequestInfo& info) {
3735 if (info.referrer() == expected_referrer_)
3736 called_start_with_referrer_ = true;
3737 }
3738
3739 virtual void OnFinishResolutionWithStatus(
3740 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3741 if (info.referrer() == expected_referrer_)
3742 called_finish_with_referrer_ = true;
3743 }
3744
[email protected]eb255d32009-06-17 02:11:033745 virtual void OnCancelResolution(int id,
3746 const HostResolver::RequestInfo& info ) {
3747 FAIL() << "Should not be cancelling any requests!";
3748 }
3749
[email protected]f3e6c1e2009-06-15 20:52:123750 bool did_complete_with_expected_referrer() const {
3751 return called_start_with_referrer_ && called_finish_with_referrer_;
3752 }
3753
3754 private:
3755 GURL expected_referrer_;
3756 bool called_start_with_referrer_;
3757 bool called_finish_with_referrer_;
3758
3759 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3760};
3761
3762// Make sure that when HostResolver::Resolve() is invoked, it passes through
3763// the "referrer". This is depended on by the DNS prefetch observer.
3764TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3765 GURL referrer = GURL("http://expected-referrer/");
3766 EXPECT_TRUE(referrer.is_valid());
3767 ResolutionReferrerObserver resolution_observer(referrer);
3768
3769 SessionDependencies session_deps;
3770 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433771 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123772
3773 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143774 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123775
3776 // Connect up a mock socket which will fail when reading.
3777 MockRead data_reads[] = {
3778 MockRead(false, ERR_FAILED),
3779 };
[email protected]31a2bfe2010-02-09 08:03:393780 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593781 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:123782
3783 // Issue a request, containing an HTTP referrer.
3784 HttpRequestInfo request;
3785 request.method = "GET";
3786 request.referrer = referrer;
3787 request.url = GURL("http://www.google.com/");
3788
3789 // Run the request until it fails reading from the socket.
3790 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463791 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123792 EXPECT_EQ(ERR_IO_PENDING, rv);
3793 rv = callback.WaitForResult();
3794 EXPECT_EQ(ERR_FAILED, rv);
3795
3796 // Check that the host resolution observer saw |referrer|.
3797 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3798}
3799
[email protected]3b9cca42009-06-16 01:08:283800// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3801// host cache is bypassed.
3802TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3803 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323804
[email protected]a2c2fb92009-07-18 07:31:043805 // Select a host resolver that does caching.
3806 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323807
[email protected]3b9cca42009-06-16 01:08:283808 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433809 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:283810
3811 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3812 // a synchronous lookup.)
3813 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143814 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463815 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3816 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283817 EXPECT_EQ(OK, rv);
3818
3819 // Verify that it was added to host cache, by doing a subsequent async lookup
3820 // and confirming it completes synchronously.
3821 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463822 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283823 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463824 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323825 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283826
3827 // Inject a failure the next time that "www.google.com" is resolved. This way
3828 // we can tell if the next lookup hit the cache, or the "network".
3829 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323830 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283831
3832 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3833 // first read -- this won't be reached as the host resolution will fail first.
3834 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:393835 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593836 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:283837
3838 // Issue a request, asking to bypass the cache(s).
3839 HttpRequestInfo request;
3840 request.method = "GET";
3841 request.load_flags = LOAD_BYPASS_CACHE;
3842 request.url = GURL("http://www.google.com/");
3843
3844 // Run the request.
3845 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463846 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283847 ASSERT_EQ(ERR_IO_PENDING, rv);
3848 rv = callback.WaitForResult();
3849
3850 // If we bypassed the cache, we would have gotten a failure while resolving
3851 // "www.google.com".
3852 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3853}
3854
[email protected]0877e3d2009-10-17 22:29:573855// Make sure we can handle an error when writing the request.
3856TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3857 SessionDependencies session_deps;
3858 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3859
3860 HttpRequestInfo request;
3861 request.method = "GET";
3862 request.url = GURL("http://www.foo.com/");
3863 request.load_flags = 0;
3864
3865 MockWrite write_failure[] = {
3866 MockWrite(true, ERR_CONNECTION_RESET),
3867 };
[email protected]31a2bfe2010-02-09 08:03:393868 StaticSocketDataProvider data(NULL, 0,
3869 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:593870 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573871
3872 TestCompletionCallback callback;
3873
3874 scoped_ptr<HttpTransaction> trans(
3875 new HttpNetworkTransaction(CreateSession(&session_deps)));
3876
3877 int rv = trans->Start(&request, &callback, NULL);
3878 EXPECT_EQ(ERR_IO_PENDING, rv);
3879
3880 rv = callback.WaitForResult();
3881 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3882}
3883
3884// Check that a connection closed after the start of the headers finishes ok.
3885TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3886 SessionDependencies session_deps;
3887 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3888
3889 HttpRequestInfo request;
3890 request.method = "GET";
3891 request.url = GURL("http://www.foo.com/");
3892 request.load_flags = 0;
3893
3894 MockRead data_reads[] = {
3895 MockRead("HTTP/1."),
3896 MockRead(false, OK),
3897 };
3898
[email protected]31a2bfe2010-02-09 08:03:393899 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593900 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573901
3902 TestCompletionCallback callback;
3903
3904 scoped_ptr<HttpTransaction> trans(
3905 new HttpNetworkTransaction(CreateSession(&session_deps)));
3906
3907 int rv = trans->Start(&request, &callback, NULL);
3908 EXPECT_EQ(ERR_IO_PENDING, rv);
3909
3910 rv = callback.WaitForResult();
3911 EXPECT_EQ(OK, rv);
3912
3913 const HttpResponseInfo* response = trans->GetResponseInfo();
3914 EXPECT_TRUE(response != NULL);
3915
3916 EXPECT_TRUE(response->headers != NULL);
3917 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
3918
3919 std::string response_data;
3920 rv = ReadTransaction(trans.get(), &response_data);
3921 EXPECT_EQ(OK, rv);
3922 EXPECT_EQ("", response_data);
3923}
3924
3925// Make sure that a dropped connection while draining the body for auth
3926// restart does the right thing.
3927TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
3928 SessionDependencies session_deps;
3929 scoped_ptr<HttpTransaction> trans(
3930 new HttpNetworkTransaction(CreateSession(&session_deps)));
3931
3932 HttpRequestInfo request;
3933 request.method = "GET";
3934 request.url = GURL("http://www.google.com/");
3935 request.load_flags = 0;
3936
3937 MockWrite data_writes1[] = {
3938 MockWrite("GET / HTTP/1.1\r\n"
3939 "Host: www.google.com\r\n"
3940 "Connection: keep-alive\r\n\r\n"),
3941 };
3942
3943 MockRead data_reads1[] = {
3944 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3945 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3946 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3947 MockRead("Content-Length: 14\r\n\r\n"),
3948 MockRead("Unauth"),
3949 MockRead(true, ERR_CONNECTION_RESET),
3950 };
3951
[email protected]31a2bfe2010-02-09 08:03:393952 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3953 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593954 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:573955
3956 // After calling trans->RestartWithAuth(), this is the request we should
3957 // be issuing -- the final header line contains the credentials.
3958 MockWrite data_writes2[] = {
3959 MockWrite("GET / HTTP/1.1\r\n"
3960 "Host: www.google.com\r\n"
3961 "Connection: keep-alive\r\n"
3962 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3963 };
3964
3965 // Lastly, the server responds with the actual content.
3966 MockRead data_reads2[] = {
3967 MockRead("HTTP/1.1 200 OK\r\n"),
3968 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3969 MockRead("Content-Length: 100\r\n\r\n"),
3970 MockRead(false, OK),
3971 };
3972
[email protected]31a2bfe2010-02-09 08:03:393973 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3974 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593975 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:573976
3977 TestCompletionCallback callback1;
3978
3979 int rv = trans->Start(&request, &callback1, NULL);
3980 EXPECT_EQ(ERR_IO_PENDING, rv);
3981
3982 rv = callback1.WaitForResult();
3983 EXPECT_EQ(OK, rv);
3984
3985 const HttpResponseInfo* response = trans->GetResponseInfo();
3986 EXPECT_FALSE(response == NULL);
3987
3988 // The password prompt info should have been set in response->auth_challenge.
3989 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3990
3991 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3992 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3993 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3994
3995 TestCompletionCallback callback2;
3996
3997 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3998 EXPECT_EQ(ERR_IO_PENDING, rv);
3999
4000 rv = callback2.WaitForResult();
4001 EXPECT_EQ(OK, rv);
4002
4003 response = trans->GetResponseInfo();
4004 EXPECT_FALSE(response == NULL);
4005 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4006 EXPECT_EQ(100, response->headers->GetContentLength());
4007}
4008
4009// Test HTTPS connections going through a proxy that sends extra data.
4010TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4011 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4012
4013 HttpRequestInfo request;
4014 request.method = "GET";
4015 request.url = GURL("https://www.google.com/");
4016 request.load_flags = 0;
4017
4018 MockRead proxy_reads[] = {
4019 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4020 MockRead(false, OK)
4021 };
4022
[email protected]31a2bfe2010-02-09 08:03:394023 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594024 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574025
[email protected]5ecc992a42009-11-11 01:41:594026 session_deps.socket_factory.AddSocketDataProvider(&data);
4027 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574028
4029 TestCompletionCallback callback;
4030
4031 session_deps.socket_factory.ResetNextMockIndexes();
4032
4033 scoped_ptr<HttpTransaction> trans(
4034 new HttpNetworkTransaction(CreateSession(&session_deps)));
4035
4036 int rv = trans->Start(&request, &callback, NULL);
4037 EXPECT_EQ(ERR_IO_PENDING, rv);
4038
4039 rv = callback.WaitForResult();
4040 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4041}
4042
[email protected]e22e1362009-11-23 21:31:124043TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464044 SessionDependencies session_deps;
4045 scoped_ptr<HttpTransaction> trans(
4046 new HttpNetworkTransaction(CreateSession(&session_deps)));
4047
4048 HttpRequestInfo request;
4049 request.method = "GET";
4050 request.url = GURL("http://www.google.com/");
4051 request.load_flags = 0;
4052
[email protected]e22e1362009-11-23 21:31:124053 MockRead data_reads[] = {
4054 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4055 MockRead(false, OK),
4056 };
[email protected]9492e4a2010-02-24 00:58:464057
4058 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4059 session_deps.socket_factory.AddSocketDataProvider(&data);
4060
4061 TestCompletionCallback callback;
4062
4063 int rv = trans->Start(&request, &callback, NULL);
4064 EXPECT_EQ(ERR_IO_PENDING, rv);
4065
4066 EXPECT_EQ(OK, callback.WaitForResult());
4067
4068 const HttpResponseInfo* response = trans->GetResponseInfo();
4069 EXPECT_TRUE(response != NULL);
4070
4071 EXPECT_TRUE(response->headers != NULL);
4072 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4073
4074 std::string response_data;
4075 rv = ReadTransaction(trans.get(), &response_data);
4076 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124077}
4078
[email protected]95d88ffe2010-02-04 21:25:334079TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4080 SessionDependencies session_deps;
4081 scoped_ptr<HttpTransaction> trans(
4082 new HttpNetworkTransaction(CreateSession(&session_deps)));
4083
4084 HttpRequestInfo request;
4085 request.method = "POST";
4086 request.url = GURL("http://www.google.com/upload");
4087 request.upload_data = new UploadData;
4088 request.load_flags = 0;
4089
4090 FilePath temp_file_path;
4091 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4092 const uint64 kFakeSize = 100000; // file is actually blank
4093
4094 std::vector<UploadData::Element> elements;
4095 UploadData::Element element;
4096 element.SetToFilePath(temp_file_path);
4097 element.SetContentLength(kFakeSize);
4098 elements.push_back(element);
4099 request.upload_data->set_elements(elements);
4100 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4101
4102 MockRead data_reads[] = {
4103 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4104 MockRead("hello world"),
4105 MockRead(false, OK),
4106 };
[email protected]31a2bfe2010-02-09 08:03:394107 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334108 session_deps.socket_factory.AddSocketDataProvider(&data);
4109
4110 TestCompletionCallback callback;
4111
4112 int rv = trans->Start(&request, &callback, NULL);
4113 EXPECT_EQ(ERR_IO_PENDING, rv);
4114
4115 rv = callback.WaitForResult();
4116 EXPECT_EQ(OK, rv);
4117
4118 const HttpResponseInfo* response = trans->GetResponseInfo();
4119 EXPECT_TRUE(response != NULL);
4120
4121 EXPECT_TRUE(response->headers != NULL);
4122 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4123
4124 std::string response_data;
4125 rv = ReadTransaction(trans.get(), &response_data);
4126 EXPECT_EQ(OK, rv);
4127 EXPECT_EQ("hello world", response_data);
4128
4129 file_util::Delete(temp_file_path, false);
4130}
4131
[email protected]6624b4622010-03-29 19:58:364132TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4133 // If we try to upload an unreadable file, the network stack should report
4134 // the file size as zero and upload zero bytes for that file.
4135 SessionDependencies session_deps;
4136 scoped_ptr<HttpTransaction> trans(
4137 new HttpNetworkTransaction(CreateSession(&session_deps)));
4138
4139 FilePath temp_file;
4140 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4141 std::string temp_file_content("Unreadable file.");
4142 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4143 temp_file_content.length()));
4144 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4145
4146 HttpRequestInfo request;
4147 request.method = "POST";
4148 request.url = GURL("http://www.google.com/upload");
4149 request.upload_data = new UploadData;
4150 request.load_flags = 0;
4151
4152 std::vector<UploadData::Element> elements;
4153 UploadData::Element element;
4154 element.SetToFilePath(temp_file);
4155 elements.push_back(element);
4156 request.upload_data->set_elements(elements);
4157
4158 MockRead data_reads[] = {
4159 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4160 MockRead(false, OK),
4161 };
4162 MockWrite data_writes[] = {
4163 MockWrite("POST /upload HTTP/1.1\r\n"
4164 "Host: www.google.com\r\n"
4165 "Connection: keep-alive\r\n"
4166 "Content-Length: 0\r\n\r\n"),
4167 MockWrite(false, OK),
4168 };
4169 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4170 arraysize(data_writes));
4171 session_deps.socket_factory.AddSocketDataProvider(&data);
4172
4173 TestCompletionCallback callback;
4174
4175 int rv = trans->Start(&request, &callback, NULL);
4176 EXPECT_EQ(ERR_IO_PENDING, rv);
4177
4178 rv = callback.WaitForResult();
4179 EXPECT_EQ(OK, rv);
4180
4181 const HttpResponseInfo* response = trans->GetResponseInfo();
4182 EXPECT_TRUE(response != NULL);
4183 EXPECT_TRUE(response->headers != NULL);
4184 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4185
4186 file_util::Delete(temp_file, false);
4187}
4188
4189TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4190 SessionDependencies session_deps;
4191 scoped_ptr<HttpTransaction> trans(
4192 new HttpNetworkTransaction(CreateSession(&session_deps)));
4193
4194 FilePath temp_file;
4195 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4196 std::string temp_file_contents("Unreadable file.");
4197 std::string unreadable_contents(temp_file_contents.length(), '\0');
4198 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4199 temp_file_contents.length()));
4200
4201 HttpRequestInfo request;
4202 request.method = "POST";
4203 request.url = GURL("http://www.google.com/upload");
4204 request.upload_data = new UploadData;
4205 request.load_flags = 0;
4206
4207 std::vector<UploadData::Element> elements;
4208 UploadData::Element element;
4209 element.SetToFilePath(temp_file);
4210 elements.push_back(element);
4211 request.upload_data->set_elements(elements);
4212
4213 MockRead data_reads[] = {
4214 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4215 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4216 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4217
4218 MockRead("HTTP/1.1 200 OK\r\n"),
4219 MockRead("Content-Length: 0\r\n\r\n"),
4220 MockRead(false, OK),
4221 };
4222 MockWrite data_writes[] = {
4223 MockWrite("POST /upload HTTP/1.1\r\n"
4224 "Host: www.google.com\r\n"
4225 "Connection: keep-alive\r\n"
4226 "Content-Length: 16\r\n\r\n"),
4227 MockWrite(false, temp_file_contents.c_str()),
4228
4229 MockWrite("POST /upload HTTP/1.1\r\n"
4230 "Host: www.google.com\r\n"
4231 "Connection: keep-alive\r\n"
4232 "Content-Length: 16\r\n"
4233 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4234 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4235 MockWrite(false, OK),
4236 };
4237 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4238 arraysize(data_writes));
4239 session_deps.socket_factory.AddSocketDataProvider(&data);
4240
4241 TestCompletionCallback callback1;
4242
4243 int rv = trans->Start(&request, &callback1, NULL);
4244 EXPECT_EQ(ERR_IO_PENDING, rv);
4245
4246 rv = callback1.WaitForResult();
4247 EXPECT_EQ(OK, rv);
4248
4249 const HttpResponseInfo* response = trans->GetResponseInfo();
4250 EXPECT_TRUE(response != NULL);
4251 EXPECT_TRUE(response->headers != NULL);
4252 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4253
4254 // The password prompt info should have been set in response->auth_challenge.
4255 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4256 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4257 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4258 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4259
4260 // Now make the file unreadable and try again.
4261 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4262
4263 TestCompletionCallback callback2;
4264
4265 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4266 EXPECT_EQ(ERR_IO_PENDING, rv);
4267
4268 rv = callback2.WaitForResult();
4269 EXPECT_EQ(OK, rv);
4270
4271 response = trans->GetResponseInfo();
4272 EXPECT_TRUE(response != NULL);
4273 EXPECT_TRUE(response->headers != NULL);
4274 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4275 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4276
4277 file_util::Delete(temp_file, false);
4278}
4279
[email protected]aeefc9e82010-02-19 16:18:274280// Tests that changes to Auth realms are treated like auth rejections.
4281TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4282 SessionDependencies session_deps;
4283 scoped_ptr<HttpTransaction> trans(
4284 new HttpNetworkTransaction(CreateSession(&session_deps)));
4285
4286 HttpRequestInfo request;
4287 request.method = "GET";
4288 request.url = GURL("http://www.google.com/");
4289 request.load_flags = 0;
4290
4291 // First transaction will request a resource and receive a Basic challenge
4292 // with realm="first_realm".
4293 MockWrite data_writes1[] = {
4294 MockWrite("GET / HTTP/1.1\r\n"
4295 "Host: www.google.com\r\n"
4296 "Connection: keep-alive\r\n"
4297 "\r\n"),
4298 };
4299 MockRead data_reads1[] = {
4300 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4301 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4302 "\r\n"),
4303 };
4304
4305 // After calling trans->RestartWithAuth(), provide an Authentication header
4306 // for first_realm. The server will reject and provide a challenge with
4307 // second_realm.
4308 MockWrite data_writes2[] = {
4309 MockWrite("GET / HTTP/1.1\r\n"
4310 "Host: www.google.com\r\n"
4311 "Connection: keep-alive\r\n"
4312 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4313 "\r\n"),
4314 };
4315 MockRead data_reads2[] = {
4316 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4317 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4318 "\r\n"),
4319 };
4320
4321 // This again fails, and goes back to first_realm. Make sure that the
4322 // entry is removed from cache.
4323 MockWrite data_writes3[] = {
4324 MockWrite("GET / HTTP/1.1\r\n"
4325 "Host: www.google.com\r\n"
4326 "Connection: keep-alive\r\n"
4327 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4328 "\r\n"),
4329 };
4330 MockRead data_reads3[] = {
4331 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4332 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4333 "\r\n"),
4334 };
4335
4336 // Try one last time (with the correct password) and get the resource.
4337 MockWrite data_writes4[] = {
4338 MockWrite("GET / HTTP/1.1\r\n"
4339 "Host: www.google.com\r\n"
4340 "Connection: keep-alive\r\n"
4341 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4342 "\r\n"),
4343 };
4344 MockRead data_reads4[] = {
4345 MockRead("HTTP/1.1 200 OK\r\n"
4346 "Content-Type: text/html; charset=iso-8859-1\r\n"
4347 "Content-Length: 100\r\n"
4348 "\r\n"),
4349 };
4350
4351 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4352 data_writes1, arraysize(data_writes1));
4353 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4354 data_writes2, arraysize(data_writes2));
4355 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4356 data_writes3, arraysize(data_writes3));
4357 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4358 data_writes4, arraysize(data_writes4));
4359 session_deps.socket_factory.AddSocketDataProvider(&data1);
4360 session_deps.socket_factory.AddSocketDataProvider(&data2);
4361 session_deps.socket_factory.AddSocketDataProvider(&data3);
4362 session_deps.socket_factory.AddSocketDataProvider(&data4);
4363
4364 TestCompletionCallback callback1;
4365
4366 // Issue the first request with Authorize headers. There should be a
4367 // password prompt for first_realm waiting to be filled in after the
4368 // transaction completes.
4369 int rv = trans->Start(&request, &callback1, NULL);
4370 EXPECT_EQ(ERR_IO_PENDING, rv);
4371 rv = callback1.WaitForResult();
4372 EXPECT_EQ(OK, rv);
4373 const HttpResponseInfo* response = trans->GetResponseInfo();
4374 ASSERT_FALSE(response == NULL);
4375 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4376 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4377 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4378 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4379
4380 // Issue the second request with an incorrect password. There should be a
4381 // password prompt for second_realm waiting to be filled in after the
4382 // transaction completes.
4383 TestCompletionCallback callback2;
4384 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4385 EXPECT_EQ(ERR_IO_PENDING, rv);
4386 rv = callback2.WaitForResult();
4387 EXPECT_EQ(OK, rv);
4388 response = trans->GetResponseInfo();
4389 ASSERT_FALSE(response == NULL);
4390 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4391 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4392 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4393 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4394
4395 // Issue the third request with another incorrect password. There should be
4396 // a password prompt for first_realm waiting to be filled in. If the password
4397 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4398 // first_realm was not correctly removed.
4399 TestCompletionCallback callback3;
4400 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4401 EXPECT_EQ(ERR_IO_PENDING, rv);
4402 rv = callback3.WaitForResult();
4403 EXPECT_EQ(OK, rv);
4404 response = trans->GetResponseInfo();
4405 ASSERT_FALSE(response == NULL);
4406 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4407 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4408 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4409 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4410
4411 // Issue the fourth request with the correct password and username.
4412 TestCompletionCallback callback4;
4413 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4414 EXPECT_EQ(ERR_IO_PENDING, rv);
4415 rv = callback4.WaitForResult();
4416 EXPECT_EQ(OK, rv);
4417 response = trans->GetResponseInfo();
4418 ASSERT_FALSE(response == NULL);
4419 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4420}
4421
[email protected]564b4912010-03-09 16:30:424422TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424423 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
4424
[email protected]564b4912010-03-09 16:30:424425 SessionDependencies session_deps;
4426
4427 MockRead data_reads[] = {
4428 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]a2cb8122010-03-10 17:22:424429 MockRead("Alternate-Protocol: 443:npn-spdy\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424430 MockRead("hello world"),
4431 MockRead(false, OK),
4432 };
4433
4434 HttpRequestInfo request;
4435 request.method = "GET";
4436 request.url = GURL("http://www.google.com/");
4437 request.load_flags = 0;
4438
4439 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4440
4441 session_deps.socket_factory.AddSocketDataProvider(&data);
4442
4443 TestCompletionCallback callback;
4444
4445 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4446 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4447
4448 int rv = trans->Start(&request, &callback, NULL);
4449 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534450
[email protected]564b4912010-03-09 16:30:424451 HostPortPair http_host_port_pair;
4452 http_host_port_pair.host = "www.google.com";
4453 http_host_port_pair.port = 80;
4454 const HttpAlternateProtocols& alternate_protocols =
4455 session->alternate_protocols();
4456 EXPECT_FALSE(
4457 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4458
4459 EXPECT_EQ(OK, callback.WaitForResult());
4460
4461 const HttpResponseInfo* response = trans->GetResponseInfo();
4462 ASSERT_TRUE(response != NULL);
4463 ASSERT_TRUE(response->headers != NULL);
4464 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4465
4466 std::string response_data;
4467 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4468 EXPECT_EQ("hello world", response_data);
4469
4470 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4471 const HttpAlternateProtocols::PortProtocolPair alternate =
4472 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4473 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4474 expected_alternate.port = 443;
[email protected]a2cb8122010-03-10 17:22:424475 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY;
[email protected]564b4912010-03-09 16:30:424476 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424477
4478 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424479}
4480
4481TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
4482 SessionDependencies session_deps;
4483
4484 HttpRequestInfo request;
4485 request.method = "GET";
4486 request.url = GURL("http://www.google.com/");
4487 request.load_flags = 0;
4488
4489 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4490 StaticSocketDataProvider first_data;
4491 first_data.set_connect_data(mock_connect);
4492 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4493
4494 MockRead data_reads[] = {
4495 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4496 MockRead("hello world"),
4497 MockRead(true, OK),
4498 };
4499 StaticSocketDataProvider second_data(
4500 data_reads, arraysize(data_reads), NULL, 0);
4501 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4502
4503 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4504 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4505 // http://crbug.com/37454.
4506 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4507
4508 TestCompletionCallback callback;
4509
4510 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4511
4512 HostPortPair http_host_port_pair;
4513 http_host_port_pair.host = "www.google.com";
4514 http_host_port_pair.port = 80;
4515 HttpAlternateProtocols* alternate_protocols =
4516 session->mutable_alternate_protocols();
4517 alternate_protocols->SetAlternateProtocolFor(
4518 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]a2cb8122010-03-10 17:22:424519 HttpAlternateProtocols::NPN_SPDY);
[email protected]564b4912010-03-09 16:30:424520
4521 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4522
4523 int rv = trans->Start(&request, &callback, NULL);
4524 EXPECT_EQ(ERR_IO_PENDING, rv);
4525 EXPECT_EQ(OK, callback.WaitForResult());
4526
4527 const HttpResponseInfo* response = trans->GetResponseInfo();
4528 ASSERT_TRUE(response != NULL);
4529 ASSERT_TRUE(response->headers != NULL);
4530 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4531
4532 std::string response_data;
4533 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4534 EXPECT_EQ("hello world", response_data);
4535
4536 ASSERT_TRUE(
4537 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
4538 const HttpAlternateProtocols::PortProtocolPair alternate =
4539 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
4540 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
4541}
4542
4543// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
4544// says that it does SPDY, but it just does the TLS handshake, but the NPN
4545// response does not indicate SPDY, so we just do standard HTTPS over the port.
4546// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
4547// on the original port.
[email protected]a2cb8122010-03-10 17:22:424548// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
4549// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:534550//
[email protected]a2cb8122010-03-10 17:22:424551// HttpRequestInfo request;
4552// request.method = "GET";
4553// request.url = GURL("http://www.google.com/");
4554// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:534555//
[email protected]a2cb8122010-03-10 17:22:424556// MockRead data_reads[] = {
4557// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4558// MockRead("hello world"),
4559// MockRead(true, OK),
4560// };
4561// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4562// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:534563//
[email protected]a2cb8122010-03-10 17:22:424564// SSLSocketDataProvider ssl(true, OK);
4565// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:534566//
[email protected]a2cb8122010-03-10 17:22:424567// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:534568//
[email protected]a2cb8122010-03-10 17:22:424569// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:534570//
[email protected]a2cb8122010-03-10 17:22:424571// HostPortPair http_host_port_pair;
4572// http_host_port_pair.host = "www.google.com";
4573// http_host_port_pair.port = 80;
4574// HttpAlternateProtocols* alternate_protocols =
4575// session->mutable_alternate_protocols();
4576// alternate_protocols->SetAlternateProtocolFor(
4577// http_host_port_pair, 1234 /* port is ignored */,
4578// HttpAlternateProtocols::NPN_SPDY);
[email protected]9e743cd2010-03-16 07:03:534579//
[email protected]a2cb8122010-03-10 17:22:424580// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:534581//
[email protected]a2cb8122010-03-10 17:22:424582// int rv = trans->Start(&request, &callback, NULL);
4583// EXPECT_EQ(ERR_IO_PENDING, rv);
4584// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:534585//
[email protected]a2cb8122010-03-10 17:22:424586// const HttpResponseInfo* response = trans->GetResponseInfo();
4587// ASSERT_TRUE(response != NULL);
4588// ASSERT_TRUE(response->headers != NULL);
4589// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:534590//
[email protected]a2cb8122010-03-10 17:22:424591// std::string response_data;
4592// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4593// EXPECT_EQ("hello world", response_data);
4594// }
4595
4596TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]564b4912010-03-09 16:30:424597 SessionDependencies session_deps;
4598
4599 HttpRequestInfo request;
4600 request.method = "GET";
4601 request.url = GURL("http://www.google.com/");
4602 request.load_flags = 0;
4603
[email protected]a2cb8122010-03-10 17:22:424604 StaticSocketDataProvider first_tcp_connect;
4605 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
4606
4607 SSLSocketDataProvider ssl(true, OK);
4608 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4609
[email protected]564b4912010-03-09 16:30:424610 MockRead data_reads[] = {
4611 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4612 MockRead("hello world"),
4613 MockRead(true, OK),
4614 };
[email protected]a2cb8122010-03-10 17:22:424615 StaticSocketDataProvider fallback_data(
4616 data_reads, arraysize(data_reads), NULL, 0);
4617 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:424618
4619 TestCompletionCallback callback;
4620
4621 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4622
4623 HostPortPair http_host_port_pair;
4624 http_host_port_pair.host = "www.google.com";
4625 http_host_port_pair.port = 80;
4626 HttpAlternateProtocols* alternate_protocols =
4627 session->mutable_alternate_protocols();
4628 alternate_protocols->SetAlternateProtocolFor(
4629 http_host_port_pair, 1234 /* port is ignored */,
[email protected]a2cb8122010-03-10 17:22:424630 HttpAlternateProtocols::NPN_SPDY);
[email protected]564b4912010-03-09 16:30:424631
4632 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4633
4634 int rv = trans->Start(&request, &callback, NULL);
4635 EXPECT_EQ(ERR_IO_PENDING, rv);
4636 EXPECT_EQ(OK, callback.WaitForResult());
4637
4638 const HttpResponseInfo* response = trans->GetResponseInfo();
4639 ASSERT_TRUE(response != NULL);
4640 ASSERT_TRUE(response->headers != NULL);
4641 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4642
4643 std::string response_data;
4644 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4645 EXPECT_EQ("hello world", response_data);
4646}
4647
[email protected]89ceba9a2009-03-21 03:46:064648} // namespace net