blob: b9458d5c5d27e12b12e3bf93f98294a3632a342d [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]9b3ef462010-04-08 01:48:3146 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()) {}
[email protected]228ff742009-06-05 01:19:5947
48 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4549 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4250 : host_resolver(new MockHostResolver),
51 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1052 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]9b3ef462010-04-08 01:48:3153 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()) {}
[email protected]228ff742009-06-05 01:19:5954
[email protected]a2c2fb92009-07-18 07:31:0455 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0956 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4257 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5958 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:5059 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]228ff742009-06-05 01:19:5960};
61
[email protected]1c773ea12009-04-28 19:58:4262ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5063 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:4864 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3965 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5366}
67
[email protected]228ff742009-06-05 01:19:5968HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]d13c3272010-02-04 00:24:5169 return new HttpNetworkSession(NULL,
70 session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:0971 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:4272 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:1073 session_deps->ssl_config_service,
[email protected]fa55e192010-02-15 14:25:5074 session_deps->http_auth_handler_factory.get());
[email protected]e8d536192008-10-17 22:21:1475}
76
[email protected]89836e22008-09-25 20:33:4277class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:5278 public:
[email protected]0e75a732008-10-16 20:36:0979 virtual void TearDown() {
80 // Empty the current queue.
81 MessageLoop::current()->RunAllPending();
82 PlatformTest::TearDown();
83 }
84
[email protected]3d2a59b2008-09-26 19:44:2585 protected:
86 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:5287
[email protected]ff007e162009-05-23 09:13:1588 struct SimpleGetHelperResult {
89 int rv;
90 std::string status_line;
91 std::string response_data;
92 };
initial.commit586acc5fe2008-07-26 22:42:5293
[email protected]31a2bfe2010-02-09 08:03:3994 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
95 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:1596 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:5297
[email protected]228ff742009-06-05 01:19:5998 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:4099 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43100 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52101
[email protected]ff007e162009-05-23 09:13:15102 HttpRequestInfo request;
103 request.method = "GET";
104 request.url = GURL("http://www.google.com/");
105 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52106
[email protected]31a2bfe2010-02-09 08:03:39107 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59108 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52109
[email protected]ff007e162009-05-23 09:13:15110 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52111
[email protected]684970b2009-08-14 04:54:46112 int rv = trans->Start(&request, &callback, NULL);
[email protected]ff007e162009-05-23 09:13:15113 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52114
[email protected]ff007e162009-05-23 09:13:15115 out.rv = callback.WaitForResult();
116 if (out.rv != OK)
117 return out;
118
119 const HttpResponseInfo* response = trans->GetResponseInfo();
120 EXPECT_TRUE(response != NULL);
121
122 EXPECT_TRUE(response->headers != NULL);
123 out.status_line = response->headers->GetStatusLine();
124
125 rv = ReadTransaction(trans.get(), &out.response_data);
126 EXPECT_EQ(OK, rv);
127
[email protected]aecfbf22008-10-16 02:02:47128 return out;
[email protected]ff007e162009-05-23 09:13:15129 }
initial.commit586acc5fe2008-07-26 22:42:52130
[email protected]ff007e162009-05-23 09:13:15131 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
132 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52133
[email protected]ff007e162009-05-23 09:13:15134 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15135};
[email protected]231d5a32008-09-13 00:45:27136
[email protected]15a5ccf82008-10-23 19:57:43137// Fill |str| with a long header list that consumes >= |size| bytes.
138void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19139 const char* row =
140 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
141 const int sizeof_row = strlen(row);
142 const int num_rows = static_cast<int>(
143 ceil(static_cast<float>(size) / sizeof_row));
144 const int sizeof_data = num_rows * sizeof_row;
145 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43146 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51147
[email protected]4ddaf2502008-10-23 18:26:19148 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43149 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19150}
151
[email protected]385a4672009-03-11 22:21:29152// Alternative functions that eliminate randomness and dependency on the local
153// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20154void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29155 static const uint8 bytes[] = {
156 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
157 };
158 static size_t current_byte = 0;
159 for (size_t i = 0; i < n; ++i) {
160 output[i] = bytes[current_byte++];
161 current_byte %= arraysize(bytes);
162 }
163}
164
[email protected]fe2bc6a2009-03-23 16:52:20165void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29166 static const uint8 bytes[] = {
167 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
168 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
169 };
170 static size_t current_byte = 0;
171 for (size_t i = 0; i < n; ++i) {
172 output[i] = bytes[current_byte++];
173 current_byte %= arraysize(bytes);
174 }
175}
176
[email protected]fe2bc6a2009-03-23 16:52:20177std::string MockGetHostName() {
178 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29179}
180
[email protected]a796bcec2010-03-22 17:17:26181template<typename EmulatedClientSocketPool, typename SocketSourceType>
182class CaptureGroupNameSocketPool : public EmulatedClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31183 public:
[email protected]a796bcec2010-03-22 17:17:26184 CaptureGroupNameSocketPool(HttpNetworkSession* session,
185 SocketSourceType* socket_source)
186 : EmulatedClientSocketPool(0, 0, "CaptureGroupNameTestPool",
[email protected]9b3ef462010-04-08 01:48:31187 session->host_resolver(), socket_source) {}
[email protected]d80a4322009-08-14 07:07:49188 const std::string last_group_name_received() const {
189 return last_group_name_;
190 }
191
[email protected]684970b2009-08-14 04:54:46192 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49193 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31194 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31195 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46196 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53197 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31198 last_group_name_ = group_name;
199 return ERR_IO_PENDING;
200 }
[email protected]04e5be32009-06-26 20:00:31201 virtual void CancelRequest(const std::string& group_name,
202 const ClientSocketHandle* handle) { }
203 virtual void ReleaseSocket(const std::string& group_name,
204 ClientSocket* socket) {}
205 virtual void CloseIdleSockets() {}
206 virtual HostResolver* GetHostResolver() const {
207 return NULL;
208 }
209 virtual int IdleSocketCount() const {
210 return 0;
211 }
212 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
213 return 0;
214 }
215 virtual LoadState GetLoadState(const std::string& group_name,
216 const ClientSocketHandle* handle) const {
217 return LOAD_STATE_IDLE;
218 }
[email protected]a796bcec2010-03-22 17:17:26219 virtual base::TimeDelta ConnectionTimeout() const {
220 return base::TimeDelta();
221 }
[email protected]d80a4322009-08-14 07:07:49222
223 private:
[email protected]04e5be32009-06-26 20:00:31224 std::string last_group_name_;
225};
226
[email protected]a796bcec2010-03-22 17:17:26227typedef CaptureGroupNameSocketPool<TCPClientSocketPool, ClientSocketFactory>
228 CaptureGroupNameTCPSocketPool;
229typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool, TCPClientSocketPool>
230 CaptureGroupNameSOCKSSocketPool;
[email protected]231d5a32008-09-13 00:45:27231//-----------------------------------------------------------------------------
232
233TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59234 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40235 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43236 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27237}
238
239TEST_F(HttpNetworkTransactionTest, SimpleGET) {
240 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35241 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
242 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42243 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27244 };
[email protected]31a2bfe2010-02-09 08:03:39245 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
246 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42247 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27248 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
249 EXPECT_EQ("hello world", out.response_data);
250}
251
252// Response with no status line.
253TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
254 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35255 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42256 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27257 };
[email protected]31a2bfe2010-02-09 08:03:39258 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
259 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42260 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27261 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
262 EXPECT_EQ("hello world", out.response_data);
263}
264
265// Allow up to 4 bytes of junk to precede status line.
266TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
267 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35268 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42269 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27270 };
[email protected]31a2bfe2010-02-09 08:03:39271 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
272 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42273 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27274 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
275 EXPECT_EQ("DATA", out.response_data);
276}
277
278// Allow up to 4 bytes of junk to precede status line.
279TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
280 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35281 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42282 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27283 };
[email protected]31a2bfe2010-02-09 08:03:39284 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
285 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42286 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27287 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
288 EXPECT_EQ("DATA", out.response_data);
289}
290
291// Beyond 4 bytes of slop and it should fail to find a status line.
292TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
293 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35294 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42295 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27296 };
[email protected]31a2bfe2010-02-09 08:03:39297 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
298 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42299 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25300 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
301 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27302}
303
304// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
305TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
306 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35307 MockRead("\n"),
308 MockRead("\n"),
309 MockRead("Q"),
310 MockRead("J"),
311 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42312 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27313 };
[email protected]31a2bfe2010-02-09 08:03:39314 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
315 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42316 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27317 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
318 EXPECT_EQ("DATA", out.response_data);
319}
320
321// Close the connection before enough bytes to have a status line.
322TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
323 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35324 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42325 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27326 };
[email protected]31a2bfe2010-02-09 08:03:39327 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
328 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42329 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27330 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
331 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52332}
333
[email protected]f9d44aa2008-09-23 23:57:17334// Simulate a 204 response, lacking a Content-Length header, sent over a
335// persistent connection. The response should still terminate since a 204
336// cannot have a response body.
337TEST_F(HttpNetworkTransactionTest, StopsReading204) {
338 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35339 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
340 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42341 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17342 };
[email protected]31a2bfe2010-02-09 08:03:39343 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
344 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42345 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17346 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
347 EXPECT_EQ("", out.response_data);
348}
349
[email protected]0877e3d2009-10-17 22:29:57350// A simple request using chunked encoding with some extra data after.
351// (Like might be seen in a pipelined response.)
352TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
353 MockRead data_reads[] = {
354 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
355 MockRead("5\r\nHello\r\n"),
356 MockRead("1\r\n"),
357 MockRead(" \r\n"),
358 MockRead("5\r\nworld\r\n"),
359 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
360 MockRead(false, OK),
361 };
[email protected]31a2bfe2010-02-09 08:03:39362 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
363 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57364 EXPECT_EQ(OK, out.rv);
365 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
366 EXPECT_EQ("Hello world", out.response_data);
367}
368
[email protected]ef0faf2e72009-03-05 23:27:23369// Do a request using the HEAD method. Verify that we don't try to read the
370// message body (since HEAD has none).
371TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59372 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40373 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43374 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23375
[email protected]1c773ea12009-04-28 19:58:42376 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23377 request.method = "HEAD";
378 request.url = GURL("http://www.google.com/");
379 request.load_flags = 0;
380
381 MockWrite data_writes1[] = {
382 MockWrite("HEAD / HTTP/1.1\r\n"
383 "Host: www.google.com\r\n"
384 "Connection: keep-alive\r\n"
385 "Content-Length: 0\r\n\r\n"),
386 };
387 MockRead data_reads1[] = {
388 MockRead("HTTP/1.1 404 Not Found\r\n"),
389 MockRead("Server: Blah\r\n"),
390 MockRead("Content-Length: 1234\r\n\r\n"),
391
392 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42393 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23394 };
395
[email protected]31a2bfe2010-02-09 08:03:39396 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
397 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59398 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23399
400 TestCompletionCallback callback1;
401
[email protected]684970b2009-08-14 04:54:46402 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42403 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23404
405 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42406 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23407
[email protected]1c773ea12009-04-28 19:58:42408 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23409 EXPECT_FALSE(response == NULL);
410
411 // Check that the headers got parsed.
412 EXPECT_TRUE(response->headers != NULL);
413 EXPECT_EQ(1234, response->headers->GetContentLength());
414 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
415
416 std::string server_header;
417 void* iter = NULL;
418 bool has_server_header = response->headers->EnumerateHeader(
419 &iter, "Server", &server_header);
420 EXPECT_TRUE(has_server_header);
421 EXPECT_EQ("Blah", server_header);
422
423 // Reading should give EOF right away, since there is no message body
424 // (despite non-zero content-length).
425 std::string response_data;
426 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42427 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23428 EXPECT_EQ("", response_data);
429}
430
initial.commit586acc5fe2008-07-26 22:42:52431TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59432 SessionDependencies session_deps;
433 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52434
435 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35436 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
437 MockRead("hello"),
438 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
439 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42440 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52441 };
[email protected]31a2bfe2010-02-09 08:03:39442 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59443 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52444
445 const char* kExpectedResponseData[] = {
446 "hello", "world"
447 };
448
449 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43450 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52451
[email protected]1c773ea12009-04-28 19:58:42452 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52453 request.method = "GET";
454 request.url = GURL("http://www.google.com/");
455 request.load_flags = 0;
456
457 TestCompletionCallback callback;
458
[email protected]684970b2009-08-14 04:54:46459 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42460 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52461
462 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42463 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52464
[email protected]1c773ea12009-04-28 19:58:42465 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52466 EXPECT_TRUE(response != NULL);
467
468 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25469 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52470
471 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57472 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42473 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25474 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52475 }
476}
477
478TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59479 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40480 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43481 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52482
[email protected]1c773ea12009-04-28 19:58:42483 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52484 request.method = "POST";
485 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42486 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52487 request.upload_data->AppendBytes("foo", 3);
488 request.load_flags = 0;
489
490 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35491 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
492 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
493 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42494 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52495 };
[email protected]31a2bfe2010-02-09 08:03:39496 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59497 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52498
499 TestCompletionCallback callback;
500
[email protected]684970b2009-08-14 04:54:46501 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42502 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52503
504 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42505 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52506
[email protected]1c773ea12009-04-28 19:58:42507 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52508 EXPECT_TRUE(response != NULL);
509
510 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25511 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52512
513 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57514 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42515 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25516 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52517}
518
[email protected]3a2d3662009-03-27 03:49:14519// This test is almost the same as Ignores100 above, but the response contains
520// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57521// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14522TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59523 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40524 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43525 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14526
[email protected]1c773ea12009-04-28 19:58:42527 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14528 request.method = "GET";
529 request.url = GURL("http://www.foo.com/");
530 request.load_flags = 0;
531
532 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57533 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
534 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14535 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42536 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14537 };
[email protected]31a2bfe2010-02-09 08:03:39538 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59539 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14540
541 TestCompletionCallback callback;
542
[email protected]684970b2009-08-14 04:54:46543 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42544 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14545
546 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42547 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14548
[email protected]1c773ea12009-04-28 19:58:42549 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14550 EXPECT_TRUE(response != NULL);
551
552 EXPECT_TRUE(response->headers != NULL);
553 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
554
555 std::string response_data;
556 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42557 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14558 EXPECT_EQ("hello world", response_data);
559}
560
[email protected]ee9410e72010-01-07 01:42:38561TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
562 SessionDependencies session_deps;
563 scoped_ptr<HttpTransaction> trans(
564 new HttpNetworkTransaction(CreateSession(&session_deps)));
565
566 HttpRequestInfo request;
567 request.method = "POST";
568 request.url = GURL("http://www.foo.com/");
569 request.load_flags = 0;
570
571 MockRead data_reads[] = {
572 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
573 MockRead(true, 0),
574 };
[email protected]31a2bfe2010-02-09 08:03:39575 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38576 session_deps.socket_factory.AddSocketDataProvider(&data);
577
578 TestCompletionCallback callback;
579
580 int rv = trans->Start(&request, &callback, NULL);
581 EXPECT_EQ(ERR_IO_PENDING, rv);
582
583 rv = callback.WaitForResult();
584 EXPECT_EQ(OK, rv);
585
586 std::string response_data;
587 rv = ReadTransaction(trans.get(), &response_data);
588 EXPECT_EQ(OK, rv);
589 EXPECT_EQ("", response_data);
590}
591
592TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
593 SessionDependencies session_deps;
594 scoped_ptr<HttpTransaction> trans(
595 new HttpNetworkTransaction(CreateSession(&session_deps)));
596
597 HttpRequestInfo request;
598 request.method = "POST";
599 request.url = GURL("http://www.foo.com/");
600 request.load_flags = 0;
601
602 MockRead data_reads[] = {
603 MockRead(true, 0),
604 };
[email protected]31a2bfe2010-02-09 08:03:39605 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38606 session_deps.socket_factory.AddSocketDataProvider(&data);
607
608 TestCompletionCallback callback;
609
610 int rv = trans->Start(&request, &callback, NULL);
611 EXPECT_EQ(ERR_IO_PENDING, rv);
612
613 rv = callback.WaitForResult();
614 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
615}
616
[email protected]3d2a59b2008-09-26 19:44:25617// read_failure specifies a read failure that should cause the network
618// transaction to resend the request.
619void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
620 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59621 SessionDependencies session_deps;
622 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52623
[email protected]1c773ea12009-04-28 19:58:42624 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52625 request.method = "GET";
626 request.url = GURL("http://www.foo.com/");
627 request.load_flags = 0;
628
629 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35630 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
631 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25632 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52633 };
[email protected]31a2bfe2010-02-09 08:03:39634 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59635 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52636
637 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35638 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
639 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42640 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52641 };
[email protected]31a2bfe2010-02-09 08:03:39642 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59643 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52644
645 const char* kExpectedResponseData[] = {
646 "hello", "world"
647 };
648
649 for (int i = 0; i < 2; ++i) {
650 TestCompletionCallback callback;
651
[email protected]5695b8c2009-09-30 21:36:43652 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52653
[email protected]684970b2009-08-14 04:54:46654 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42655 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52656
657 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42658 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52659
[email protected]1c773ea12009-04-28 19:58:42660 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52661 EXPECT_TRUE(response != NULL);
662
663 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25664 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52665
666 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57667 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42668 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25669 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52670 }
671}
[email protected]3d2a59b2008-09-26 19:44:25672
673TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42674 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25675 KeepAliveConnectionResendRequestTest(read_failure);
676}
677
678TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42679 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25680 KeepAliveConnectionResendRequestTest(read_failure);
681}
682
683TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59684 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40685 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43686 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25687
[email protected]1c773ea12009-04-28 19:58:42688 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25689 request.method = "GET";
690 request.url = GURL("http://www.google.com/");
691 request.load_flags = 0;
692
693 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42694 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35695 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
696 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42697 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25698 };
[email protected]31a2bfe2010-02-09 08:03:39699 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59700 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25701
702 TestCompletionCallback callback;
703
[email protected]684970b2009-08-14 04:54:46704 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42705 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25706
707 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42708 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25709
[email protected]1c773ea12009-04-28 19:58:42710 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25711 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25712}
713
714// What do various browsers do when the server closes a non-keepalive
715// connection without sending any response header or body?
716//
717// IE7: error page
718// Safari 3.1.2 (Windows): error page
719// Firefox 3.0.1: blank page
720// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42721// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
722// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25723TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
724 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42725 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35726 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
727 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42728 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25729 };
[email protected]31a2bfe2010-02-09 08:03:39730 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
731 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42732 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25733}
[email protected]038e9a32008-10-08 22:40:16734
735// Test the request-challenge-retry sequence for basic auth.
736// (basic auth is the easiest to mock, because it has no randomness).
737TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59738 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40739 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43740 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16741
[email protected]1c773ea12009-04-28 19:58:42742 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16743 request.method = "GET";
744 request.url = GURL("http://www.google.com/");
745 request.load_flags = 0;
746
[email protected]f9ee6b52008-11-08 06:46:23747 MockWrite data_writes1[] = {
748 MockWrite("GET / HTTP/1.1\r\n"
749 "Host: www.google.com\r\n"
750 "Connection: keep-alive\r\n\r\n"),
751 };
752
[email protected]038e9a32008-10-08 22:40:16753 MockRead data_reads1[] = {
754 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
755 // Give a couple authenticate options (only the middle one is actually
756 // supported).
[email protected]22927ad2009-09-21 19:56:19757 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16758 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
759 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
760 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
761 // Large content-length -- won't matter, as connection will be reset.
762 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42763 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16764 };
765
766 // After calling trans->RestartWithAuth(), this is the request we should
767 // be issuing -- the final header line contains the credentials.
768 MockWrite data_writes2[] = {
769 MockWrite("GET / HTTP/1.1\r\n"
770 "Host: www.google.com\r\n"
771 "Connection: keep-alive\r\n"
772 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
773 };
774
775 // Lastly, the server responds with the actual content.
776 MockRead data_reads2[] = {
777 MockRead("HTTP/1.0 200 OK\r\n"),
778 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
779 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42780 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16781 };
782
[email protected]31a2bfe2010-02-09 08:03:39783 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
784 data_writes1, arraysize(data_writes1));
785 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
786 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59787 session_deps.socket_factory.AddSocketDataProvider(&data1);
788 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16789
790 TestCompletionCallback callback1;
791
[email protected]684970b2009-08-14 04:54:46792 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42793 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16794
795 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42796 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16797
[email protected]1c773ea12009-04-28 19:58:42798 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16799 EXPECT_FALSE(response == NULL);
800
801 // The password prompt info should have been set in response->auth_challenge.
802 EXPECT_FALSE(response->auth_challenge.get() == NULL);
803
[email protected]71e4573a2009-05-21 22:03:00804 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16805 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
806 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
807
808 TestCompletionCallback callback2;
809
810 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42811 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16812
813 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42814 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16815
816 response = trans->GetResponseInfo();
817 EXPECT_FALSE(response == NULL);
818 EXPECT_TRUE(response->auth_challenge.get() == NULL);
819 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16820}
821
[email protected]861fcd52009-08-26 02:33:46822TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
823 SessionDependencies session_deps;
824 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43825 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46826
827 HttpRequestInfo request;
828 request.method = "GET";
829 request.url = GURL("http://www.google.com/");
830 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
831
832 MockWrite data_writes[] = {
833 MockWrite("GET / HTTP/1.1\r\n"
834 "Host: www.google.com\r\n"
835 "Connection: keep-alive\r\n\r\n"),
836 };
837
838 MockRead data_reads[] = {
839 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
840 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
841 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
842 // Large content-length -- won't matter, as connection will be reset.
843 MockRead("Content-Length: 10000\r\n\r\n"),
844 MockRead(false, ERR_FAILED),
845 };
846
[email protected]31a2bfe2010-02-09 08:03:39847 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
848 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59849 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46850 TestCompletionCallback callback;
851
852 int rv = trans->Start(&request, &callback, NULL);
853 EXPECT_EQ(ERR_IO_PENDING, rv);
854
855 rv = callback.WaitForResult();
856 EXPECT_EQ(0, rv);
857
858 const HttpResponseInfo* response = trans->GetResponseInfo();
859 ASSERT_FALSE(response == NULL);
860 EXPECT_TRUE(response->auth_challenge.get() == NULL);
861}
862
[email protected]2d2697f92009-02-18 21:00:32863// Test the request-challenge-retry sequence for basic auth, over a keep-alive
864// connection.
865TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59866 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40867 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43868 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32869
[email protected]1c773ea12009-04-28 19:58:42870 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32871 request.method = "GET";
872 request.url = GURL("http://www.google.com/");
873 request.load_flags = 0;
874
875 MockWrite data_writes1[] = {
876 MockWrite("GET / HTTP/1.1\r\n"
877 "Host: www.google.com\r\n"
878 "Connection: keep-alive\r\n\r\n"),
879
880 // After calling trans->RestartWithAuth(), this is the request we should
881 // be issuing -- the final header line contains the credentials.
882 MockWrite("GET / HTTP/1.1\r\n"
883 "Host: www.google.com\r\n"
884 "Connection: keep-alive\r\n"
885 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
886 };
887
888 MockRead data_reads1[] = {
889 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
890 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
891 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
892 MockRead("Content-Length: 14\r\n\r\n"),
893 MockRead("Unauthorized\r\n"),
894
895 // Lastly, the server responds with the actual content.
896 MockRead("HTTP/1.1 200 OK\r\n"),
897 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
898 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42899 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32900 };
901
[email protected]31a2bfe2010-02-09 08:03:39902 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
903 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59904 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32905
906 TestCompletionCallback callback1;
907
[email protected]684970b2009-08-14 04:54:46908 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42909 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32910
911 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42912 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32913
[email protected]1c773ea12009-04-28 19:58:42914 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32915 EXPECT_FALSE(response == NULL);
916
917 // The password prompt info should have been set in response->auth_challenge.
918 EXPECT_FALSE(response->auth_challenge.get() == NULL);
919
[email protected]71e4573a2009-05-21 22:03:00920 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32921 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
922 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
923
924 TestCompletionCallback callback2;
925
926 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42927 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32928
929 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42930 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32931
932 response = trans->GetResponseInfo();
933 EXPECT_FALSE(response == NULL);
934 EXPECT_TRUE(response->auth_challenge.get() == NULL);
935 EXPECT_EQ(100, response->headers->GetContentLength());
936}
937
938// Test the request-challenge-retry sequence for basic auth, over a keep-alive
939// connection and with no response body to drain.
940TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59941 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40942 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43943 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32944
[email protected]1c773ea12009-04-28 19:58:42945 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32946 request.method = "GET";
947 request.url = GURL("http://www.google.com/");
948 request.load_flags = 0;
949
950 MockWrite data_writes1[] = {
951 MockWrite("GET / HTTP/1.1\r\n"
952 "Host: www.google.com\r\n"
953 "Connection: keep-alive\r\n\r\n"),
954
955 // After calling trans->RestartWithAuth(), this is the request we should
956 // be issuing -- the final header line contains the credentials.
957 MockWrite("GET / HTTP/1.1\r\n"
958 "Host: www.google.com\r\n"
959 "Connection: keep-alive\r\n"
960 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
961 };
962
[email protected]2d2697f92009-02-18 21:00:32963 MockRead data_reads1[] = {
964 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
965 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:31966 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:32967
968 // Lastly, the server responds with the actual content.
969 MockRead("HTTP/1.1 200 OK\r\n"),
970 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
971 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42972 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32973 };
974
[email protected]31a2bfe2010-02-09 08:03:39975 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
976 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59977 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32978
979 TestCompletionCallback callback1;
980
[email protected]684970b2009-08-14 04:54:46981 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42982 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32983
984 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42985 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32986
[email protected]1c773ea12009-04-28 19:58:42987 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32988 EXPECT_FALSE(response == NULL);
989
990 // The password prompt info should have been set in response->auth_challenge.
991 EXPECT_FALSE(response->auth_challenge.get() == NULL);
992
[email protected]71e4573a2009-05-21 22:03:00993 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32994 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
995 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
996
997 TestCompletionCallback callback2;
998
999 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421000 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321001
1002 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421003 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321004
1005 response = trans->GetResponseInfo();
1006 EXPECT_FALSE(response == NULL);
1007 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1008 EXPECT_EQ(100, response->headers->GetContentLength());
1009}
1010
1011// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1012// connection and with a large response body to drain.
1013TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591014 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401015 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431016 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321017
[email protected]1c773ea12009-04-28 19:58:421018 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321019 request.method = "GET";
1020 request.url = GURL("http://www.google.com/");
1021 request.load_flags = 0;
1022
1023 MockWrite data_writes1[] = {
1024 MockWrite("GET / HTTP/1.1\r\n"
1025 "Host: www.google.com\r\n"
1026 "Connection: keep-alive\r\n\r\n"),
1027
1028 // After calling trans->RestartWithAuth(), this is the request we should
1029 // be issuing -- the final header line contains the credentials.
1030 MockWrite("GET / HTTP/1.1\r\n"
1031 "Host: www.google.com\r\n"
1032 "Connection: keep-alive\r\n"
1033 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1034 };
1035
1036 // Respond with 5 kb of response body.
1037 std::string large_body_string("Unauthorized");
1038 large_body_string.append(5 * 1024, ' ');
1039 large_body_string.append("\r\n");
1040
1041 MockRead data_reads1[] = {
1042 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1043 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1044 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1045 // 5134 = 12 + 5 * 1024 + 2
1046 MockRead("Content-Length: 5134\r\n\r\n"),
1047 MockRead(true, large_body_string.data(), large_body_string.size()),
1048
1049 // Lastly, the server responds with the actual content.
1050 MockRead("HTTP/1.1 200 OK\r\n"),
1051 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1052 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421053 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321054 };
1055
[email protected]31a2bfe2010-02-09 08:03:391056 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1057 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591058 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321059
1060 TestCompletionCallback callback1;
1061
[email protected]684970b2009-08-14 04:54:461062 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421063 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321064
1065 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421066 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321067
[email protected]1c773ea12009-04-28 19:58:421068 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321069 EXPECT_FALSE(response == NULL);
1070
1071 // The password prompt info should have been set in response->auth_challenge.
1072 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1073
[email protected]71e4573a2009-05-21 22:03:001074 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321075 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1076 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1077
1078 TestCompletionCallback callback2;
1079
1080 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421081 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321082
1083 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421084 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321085
1086 response = trans->GetResponseInfo();
1087 EXPECT_FALSE(response == NULL);
1088 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1089 EXPECT_EQ(100, response->headers->GetContentLength());
1090}
1091
1092// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311093// connection, but the server gets impatient and closes the connection.
1094TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1095 SessionDependencies session_deps;
1096 scoped_ptr<HttpTransaction> trans(
1097 new HttpNetworkTransaction(CreateSession(&session_deps)));
1098
1099 HttpRequestInfo request;
1100 request.method = "GET";
1101 request.url = GURL("http://www.google.com/");
1102 request.load_flags = 0;
1103
1104 MockWrite data_writes1[] = {
1105 MockWrite("GET / HTTP/1.1\r\n"
1106 "Host: www.google.com\r\n"
1107 "Connection: keep-alive\r\n\r\n"),
1108 // This simulates the seemingly successful write to a closed connection
1109 // if the bug is not fixed.
1110 MockWrite("GET / HTTP/1.1\r\n"
1111 "Host: www.google.com\r\n"
1112 "Connection: keep-alive\r\n"
1113 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1114 };
1115
1116 MockRead data_reads1[] = {
1117 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1118 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1119 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1120 MockRead("Content-Length: 14\r\n\r\n"),
1121 // Tell MockTCPClientSocket to simulate the server closing the connection.
1122 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1123 MockRead("Unauthorized\r\n"),
1124 MockRead(false, OK), // The server closes the connection.
1125 };
1126
1127 // After calling trans->RestartWithAuth(), this is the request we should
1128 // be issuing -- the final header line contains the credentials.
1129 MockWrite data_writes2[] = {
1130 MockWrite("GET / HTTP/1.1\r\n"
1131 "Host: www.google.com\r\n"
1132 "Connection: keep-alive\r\n"
1133 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1134 };
1135
1136 // Lastly, the server responds with the actual content.
1137 MockRead data_reads2[] = {
1138 MockRead("HTTP/1.1 200 OK\r\n"),
1139 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1140 MockRead("Content-Length: 100\r\n\r\n"),
1141 MockRead(false, OK),
1142 };
1143
[email protected]31a2bfe2010-02-09 08:03:391144 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1145 data_writes1, arraysize(data_writes1));
1146 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1147 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311148 session_deps.socket_factory.AddSocketDataProvider(&data1);
1149 session_deps.socket_factory.AddSocketDataProvider(&data2);
1150
1151 TestCompletionCallback callback1;
1152
1153 int rv = trans->Start(&request, &callback1, NULL);
1154 EXPECT_EQ(ERR_IO_PENDING, rv);
1155
1156 rv = callback1.WaitForResult();
1157 EXPECT_EQ(OK, rv);
1158
1159 const HttpResponseInfo* response = trans->GetResponseInfo();
1160 EXPECT_FALSE(response == NULL);
1161
1162 // The password prompt info should have been set in response->auth_challenge.
1163 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1164
1165 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1166 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1167 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1168
1169 TestCompletionCallback callback2;
1170
1171 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1172 EXPECT_EQ(ERR_IO_PENDING, rv);
1173
1174 rv = callback2.WaitForResult();
1175 EXPECT_EQ(OK, rv);
1176
1177 response = trans->GetResponseInfo();
1178 ASSERT_FALSE(response == NULL);
1179 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1180 EXPECT_EQ(100, response->headers->GetContentLength());
1181}
1182
1183// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321184// proxy connection, when setting up an SSL tunnel.
1185TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1186 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591187 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1188 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321189
[email protected]5695b8c2009-09-30 21:36:431190 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321191
[email protected]1c773ea12009-04-28 19:58:421192 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321193 request.method = "GET";
1194 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461195 // Ensure that proxy authentication is attempted even
1196 // when the no authentication data flag is set.
1197 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321198
1199 // Since we have proxy, should try to establish tunnel.
1200 MockWrite data_writes1[] = {
1201 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451202 "Host: www.google.com\r\n"
1203 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321204
1205 // After calling trans->RestartWithAuth(), this is the request we should
1206 // be issuing -- the final header line contains the credentials.
1207 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1208 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451209 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321210 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1211 };
1212
1213 // The proxy responds to the connect with a 407, using a persistent
1214 // connection.
1215 MockRead data_reads1[] = {
1216 // No credentials.
1217 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1218 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1219 MockRead("Content-Length: 10\r\n\r\n"),
1220 MockRead("0123456789"),
1221
1222 // Wrong credentials (wrong password).
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 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421227 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321228 };
1229
[email protected]31a2bfe2010-02-09 08:03:391230 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1231 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591232 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321233
1234 TestCompletionCallback callback1;
1235
[email protected]684970b2009-08-14 04:54:461236 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421237 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321238
1239 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421240 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321241
[email protected]1c773ea12009-04-28 19:58:421242 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321243 EXPECT_FALSE(response == NULL);
1244
1245 EXPECT_TRUE(response->headers->IsKeepAlive());
1246 EXPECT_EQ(407, response->headers->response_code());
1247 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421248 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321249
1250 // The password prompt info should have been set in response->auth_challenge.
1251 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1252
[email protected]71e4573a2009-05-21 22:03:001253 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321254 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1255 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1256
1257 TestCompletionCallback callback2;
1258
1259 // Wrong password (should be "bar").
1260 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421261 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321262
1263 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421264 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321265
1266 response = trans->GetResponseInfo();
1267 EXPECT_FALSE(response == NULL);
1268
1269 EXPECT_TRUE(response->headers->IsKeepAlive());
1270 EXPECT_EQ(407, response->headers->response_code());
1271 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421272 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321273
1274 // The password prompt info should have been set in response->auth_challenge.
1275 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1276
[email protected]71e4573a2009-05-21 22:03:001277 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321278 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1279 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1280}
1281
[email protected]a8e9b162009-03-12 00:06:441282// Test that we don't read the response body when we fail to establish a tunnel,
1283// even if the user cancels the proxy's auth attempt.
1284TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1285 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591286 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441287
[email protected]e44de5d2009-06-05 20:12:451288 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441289
[email protected]5695b8c2009-09-30 21:36:431290 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441291
[email protected]1c773ea12009-04-28 19:58:421292 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441293 request.method = "GET";
1294 request.url = GURL("https://www.google.com/");
1295 request.load_flags = 0;
1296
1297 // Since we have proxy, should try to establish tunnel.
1298 MockWrite data_writes[] = {
1299 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451300 "Host: www.google.com\r\n"
1301 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441302 };
1303
1304 // The proxy responds to the connect with a 407.
1305 MockRead data_reads[] = {
1306 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1307 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1308 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421309 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441310 };
1311
[email protected]31a2bfe2010-02-09 08:03:391312 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1313 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591314 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441315
1316 TestCompletionCallback callback;
1317
[email protected]684970b2009-08-14 04:54:461318 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421319 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441320
1321 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421322 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441323
[email protected]1c773ea12009-04-28 19:58:421324 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441325 EXPECT_FALSE(response == NULL);
1326
1327 EXPECT_TRUE(response->headers->IsKeepAlive());
1328 EXPECT_EQ(407, response->headers->response_code());
1329 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421330 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441331
1332 std::string response_data;
1333 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421334 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441335}
1336
[email protected]ff007e162009-05-23 09:13:151337void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081338 const MockRead& status, int expected_status) {
1339 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591340 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081341
[email protected]228ff742009-06-05 01:19:591342 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081343
[email protected]5695b8c2009-09-30 21:36:431344 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081345
[email protected]1c773ea12009-04-28 19:58:421346 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081347 request.method = "GET";
1348 request.url = GURL("https://www.google.com/");
1349 request.load_flags = 0;
1350
1351 // Since we have proxy, should try to establish tunnel.
1352 MockWrite data_writes[] = {
1353 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451354 "Host: www.google.com\r\n"
1355 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081356 };
1357
1358 MockRead data_reads[] = {
1359 status,
1360 MockRead("Content-Length: 10\r\n\r\n"),
1361 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421362 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081363 };
1364
[email protected]31a2bfe2010-02-09 08:03:391365 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1366 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591367 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081368
1369 TestCompletionCallback callback;
1370
[email protected]684970b2009-08-14 04:54:461371 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421372 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081373
1374 rv = callback.WaitForResult();
1375 EXPECT_EQ(expected_status, rv);
1376}
1377
[email protected]ff007e162009-05-23 09:13:151378void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081379 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421380 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081381}
1382
1383TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1384 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1385}
1386
1387TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1388 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1389}
1390
1391TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1392 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1393}
1394
1395TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1396 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1397}
1398
1399TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1400 ConnectStatusHelper(
1401 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1402}
1403
1404TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1405 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1406}
1407
1408TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1409 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1410}
1411
1412TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1413 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1414}
1415
1416TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1417 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1418}
1419
1420TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1421 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1422}
1423
1424TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1425 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1426}
1427
1428TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1429 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1430}
1431
1432TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1433 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1434}
1435
1436TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1437 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1438}
1439
1440TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1441 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1442}
1443
1444TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1445 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1446}
1447
1448TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1449 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1450}
1451
1452TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1453 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1454}
1455
1456TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1457 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1458}
1459
1460TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1461 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1462}
1463
1464TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1465 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1466}
1467
1468TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1469 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1470}
1471
1472TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1473 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1474}
1475
1476TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1477 ConnectStatusHelperWithExpectedStatus(
1478 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421479 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081480}
1481
1482TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1483 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1484}
1485
1486TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1487 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1488}
1489
1490TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1491 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1492}
1493
1494TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1495 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1496}
1497
1498TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1499 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1500}
1501
1502TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1503 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1504}
1505
1506TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1507 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1508}
1509
1510TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1511 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1512}
1513
1514TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1515 ConnectStatusHelper(
1516 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1517}
1518
1519TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1520 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1521}
1522
1523TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1524 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1525}
1526
1527TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1528 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1529}
1530
1531TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1532 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1533}
1534
1535TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1536 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1537}
1538
1539TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1540 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1541}
1542
1543TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1544 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1545}
1546
[email protected]038e9a32008-10-08 22:40:161547// Test the flow when both the proxy server AND origin server require
1548// authentication. Again, this uses basic auth for both since that is
1549// the simplest to mock.
1550TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591551 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011552
[email protected]038e9a32008-10-08 22:40:161553 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421554 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431555 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161556
[email protected]1c773ea12009-04-28 19:58:421557 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161558 request.method = "GET";
1559 request.url = GURL("http://www.google.com/");
1560 request.load_flags = 0;
1561
[email protected]f9ee6b52008-11-08 06:46:231562 MockWrite data_writes1[] = {
1563 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1564 "Host: www.google.com\r\n"
1565 "Proxy-Connection: keep-alive\r\n\r\n"),
1566 };
1567
[email protected]038e9a32008-10-08 22:40:161568 MockRead data_reads1[] = {
1569 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1570 // Give a couple authenticate options (only the middle one is actually
1571 // supported).
[email protected]22927ad2009-09-21 19:56:191572 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161573 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1574 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1575 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1576 // Large content-length -- won't matter, as connection will be reset.
1577 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421578 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161579 };
1580
1581 // After calling trans->RestartWithAuth() the first time, this is the
1582 // request we should be issuing -- the final header line contains the
1583 // proxy's credentials.
1584 MockWrite data_writes2[] = {
1585 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1586 "Host: www.google.com\r\n"
1587 "Proxy-Connection: keep-alive\r\n"
1588 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1589 };
1590
1591 // Now the proxy server lets the request pass through to origin server.
1592 // The origin server responds with a 401.
1593 MockRead data_reads2[] = {
1594 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1595 // Note: We are using the same realm-name as the proxy server. This is
1596 // completely valid, as realms are unique across hosts.
1597 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1598 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1599 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421600 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161601 };
1602
1603 // After calling trans->RestartWithAuth() the second time, we should send
1604 // the credentials for both the proxy and origin server.
1605 MockWrite data_writes3[] = {
1606 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1607 "Host: www.google.com\r\n"
1608 "Proxy-Connection: keep-alive\r\n"
1609 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1610 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1611 };
1612
1613 // Lastly we get the desired content.
1614 MockRead data_reads3[] = {
1615 MockRead("HTTP/1.0 200 OK\r\n"),
1616 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1617 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421618 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161619 };
1620
[email protected]31a2bfe2010-02-09 08:03:391621 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1622 data_writes1, arraysize(data_writes1));
1623 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1624 data_writes2, arraysize(data_writes2));
1625 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1626 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591627 session_deps.socket_factory.AddSocketDataProvider(&data1);
1628 session_deps.socket_factory.AddSocketDataProvider(&data2);
1629 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161630
1631 TestCompletionCallback callback1;
1632
[email protected]684970b2009-08-14 04:54:461633 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421634 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161635
1636 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421637 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161638
[email protected]1c773ea12009-04-28 19:58:421639 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161640 EXPECT_FALSE(response == NULL);
1641
1642 // The password prompt info should have been set in response->auth_challenge.
1643 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1644
[email protected]71e4573a2009-05-21 22:03:001645 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161646 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1647 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1648
1649 TestCompletionCallback callback2;
1650
1651 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421652 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161653
1654 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421655 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161656
1657 response = trans->GetResponseInfo();
1658 EXPECT_FALSE(response == NULL);
1659 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1660
[email protected]71e4573a2009-05-21 22:03:001661 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161662 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1663 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1664
1665 TestCompletionCallback callback3;
1666
1667 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421668 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161669
1670 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421671 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161672
1673 response = trans->GetResponseInfo();
1674 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1675 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161676}
[email protected]4ddaf2502008-10-23 18:26:191677
[email protected]ea9dc9a2009-09-05 00:43:321678// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1679// can't hook into its internals to cause it to generate predictable NTLM
1680// authorization headers.
1681#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291682// The NTLM authentication unit tests were generated by capturing the HTTP
1683// requests and responses using Fiddler 2 and inspecting the generated random
1684// bytes in the debugger.
1685
1686// Enter the correct password and authenticate successfully.
1687TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421688 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201689 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591690 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401691 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431692 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241693
[email protected]1c773ea12009-04-28 19:58:421694 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241695 request.method = "GET";
1696 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1697 request.load_flags = 0;
1698
1699 MockWrite data_writes1[] = {
1700 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1701 "Host: 172.22.68.17\r\n"
1702 "Connection: keep-alive\r\n\r\n"),
1703 };
1704
1705 MockRead data_reads1[] = {
1706 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1707 // Negotiate and NTLM are often requested together. We only support NTLM.
1708 MockRead("WWW-Authenticate: Negotiate\r\n"),
1709 MockRead("WWW-Authenticate: NTLM\r\n"),
1710 MockRead("Connection: close\r\n"),
1711 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361712 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241713 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421714 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241715 };
1716
1717 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221718 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241719 // request we should be issuing -- the final header line contains a Type
1720 // 1 message.
1721 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1722 "Host: 172.22.68.17\r\n"
1723 "Connection: keep-alive\r\n"
1724 "Authorization: NTLM "
1725 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1726
1727 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1728 // (the credentials for the origin server). The second request continues
1729 // on the same connection.
1730 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1731 "Host: 172.22.68.17\r\n"
1732 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291733 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1734 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1735 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1736 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1737 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241738 };
1739
1740 MockRead data_reads2[] = {
1741 // The origin server responds with a Type 2 message.
1742 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1743 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291744 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241745 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1746 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1747 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1748 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1749 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1750 "BtAAAAAAA=\r\n"),
1751 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361752 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241753 MockRead("You are not authorized to view this page\r\n"),
1754
1755 // Lastly we get the desired content.
1756 MockRead("HTTP/1.1 200 OK\r\n"),
1757 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1758 MockRead("Content-Length: 13\r\n\r\n"),
1759 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421760 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241761 };
1762
[email protected]31a2bfe2010-02-09 08:03:391763 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1764 data_writes1, arraysize(data_writes1));
1765 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1766 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591767 session_deps.socket_factory.AddSocketDataProvider(&data1);
1768 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241769
1770 TestCompletionCallback callback1;
1771
[email protected]684970b2009-08-14 04:54:461772 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421773 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241774
1775 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421776 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241777
[email protected]0757e7702009-03-27 04:00:221778 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1779 TestCompletionCallback callback2;
1780 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421781 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221782 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421783 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221784 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1785
[email protected]1c773ea12009-04-28 19:58:421786 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241787 EXPECT_FALSE(response == NULL);
1788
1789 // The password prompt info should have been set in response->auth_challenge.
1790 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1791
[email protected]71e4573a2009-05-21 22:03:001792 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241793 EXPECT_EQ(L"", response->auth_challenge->realm);
1794 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1795
[email protected]0757e7702009-03-27 04:00:221796 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241797
[email protected]0757e7702009-03-27 04:00:221798 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421799 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241800
[email protected]0757e7702009-03-27 04:00:221801 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421802 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241803
1804 response = trans->GetResponseInfo();
1805 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1806 EXPECT_EQ(13, response->headers->GetContentLength());
1807}
1808
[email protected]385a4672009-03-11 22:21:291809// Enter a wrong password, and then the correct one.
1810TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421811 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201812 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591813 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401814 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431815 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291816
[email protected]1c773ea12009-04-28 19:58:421817 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291818 request.method = "GET";
1819 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1820 request.load_flags = 0;
1821
1822 MockWrite data_writes1[] = {
1823 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1824 "Host: 172.22.68.17\r\n"
1825 "Connection: keep-alive\r\n\r\n"),
1826 };
1827
1828 MockRead data_reads1[] = {
1829 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1830 // Negotiate and NTLM are often requested together. We only support NTLM.
1831 MockRead("WWW-Authenticate: Negotiate\r\n"),
1832 MockRead("WWW-Authenticate: NTLM\r\n"),
1833 MockRead("Connection: close\r\n"),
1834 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361835 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291836 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421837 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291838 };
1839
1840 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221841 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291842 // request we should be issuing -- the final header line contains a Type
1843 // 1 message.
1844 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1845 "Host: 172.22.68.17\r\n"
1846 "Connection: keep-alive\r\n"
1847 "Authorization: NTLM "
1848 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1849
1850 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1851 // (the credentials for the origin server). The second request continues
1852 // on the same connection.
1853 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1854 "Host: 172.22.68.17\r\n"
1855 "Connection: keep-alive\r\n"
1856 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1857 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1858 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1859 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1860 "4Ww7b7E=\r\n\r\n"),
1861 };
1862
1863 MockRead data_reads2[] = {
1864 // The origin server responds with a Type 2 message.
1865 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1866 MockRead("WWW-Authenticate: NTLM "
1867 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1868 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1869 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1870 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1871 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1872 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1873 "BtAAAAAAA=\r\n"),
1874 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361875 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291876 MockRead("You are not authorized to view this page\r\n"),
1877
1878 // Wrong password.
1879 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1880 MockRead("WWW-Authenticate: Negotiate\r\n"),
1881 MockRead("WWW-Authenticate: NTLM\r\n"),
1882 MockRead("Connection: close\r\n"),
1883 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361884 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291885 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421886 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291887 };
1888
1889 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221890 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291891 // request we should be issuing -- the final header line contains a Type
1892 // 1 message.
1893 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1894 "Host: 172.22.68.17\r\n"
1895 "Connection: keep-alive\r\n"
1896 "Authorization: NTLM "
1897 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1898
1899 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1900 // (the credentials for the origin server). The second request continues
1901 // on the same connection.
1902 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1903 "Host: 172.22.68.17\r\n"
1904 "Connection: keep-alive\r\n"
1905 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1906 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1907 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1908 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1909 "+4MUm7c=\r\n\r\n"),
1910 };
1911
1912 MockRead data_reads3[] = {
1913 // The origin server responds with a Type 2 message.
1914 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1915 MockRead("WWW-Authenticate: NTLM "
1916 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1917 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1918 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1919 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1920 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1921 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1922 "BtAAAAAAA=\r\n"),
1923 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361924 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291925 MockRead("You are not authorized to view this page\r\n"),
1926
1927 // Lastly we get the desired content.
1928 MockRead("HTTP/1.1 200 OK\r\n"),
1929 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1930 MockRead("Content-Length: 13\r\n\r\n"),
1931 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421932 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291933 };
1934
[email protected]31a2bfe2010-02-09 08:03:391935 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1936 data_writes1, arraysize(data_writes1));
1937 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1938 data_writes2, arraysize(data_writes2));
1939 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1940 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591941 session_deps.socket_factory.AddSocketDataProvider(&data1);
1942 session_deps.socket_factory.AddSocketDataProvider(&data2);
1943 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:291944
1945 TestCompletionCallback callback1;
1946
[email protected]684970b2009-08-14 04:54:461947 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421948 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291949
1950 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421951 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291952
[email protected]0757e7702009-03-27 04:00:221953 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291954 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221955 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421956 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291957 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421958 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221959 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291960
[email protected]1c773ea12009-04-28 19:58:421961 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291962 EXPECT_FALSE(response == NULL);
1963
1964 // The password prompt info should have been set in response->auth_challenge.
1965 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1966
[email protected]71e4573a2009-05-21 22:03:001967 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291968 EXPECT_EQ(L"", response->auth_challenge->realm);
1969 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1970
1971 TestCompletionCallback callback3;
1972
[email protected]0757e7702009-03-27 04:00:221973 // Enter the wrong password.
1974 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421975 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291976
1977 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421978 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291979
[email protected]0757e7702009-03-27 04:00:221980 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1981 TestCompletionCallback callback4;
1982 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421983 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221984 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421985 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221986 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1987
1988 response = trans->GetResponseInfo();
1989 EXPECT_FALSE(response == NULL);
1990
1991 // The password prompt info should have been set in response->auth_challenge.
1992 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1993
[email protected]71e4573a2009-05-21 22:03:001994 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221995 EXPECT_EQ(L"", response->auth_challenge->realm);
1996 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1997
1998 TestCompletionCallback callback5;
1999
2000 // Now enter the right password.
2001 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422002 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222003
2004 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422005 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222006
[email protected]385a4672009-03-11 22:21:292007 response = trans->GetResponseInfo();
2008 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2009 EXPECT_EQ(13, response->headers->GetContentLength());
2010}
[email protected]ea9dc9a2009-09-05 00:43:322011#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292012
[email protected]4ddaf2502008-10-23 18:26:192013// Test reading a server response which has only headers, and no body.
2014// After some maximum number of bytes is consumed, the transaction should
2015// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2016TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592017 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402018 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432019 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192020
[email protected]1c773ea12009-04-28 19:58:422021 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192022 request.method = "GET";
2023 request.url = GURL("http://www.google.com/");
2024 request.load_flags = 0;
2025
[email protected]b75b7b2f2009-10-06 00:54:532026 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432027 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532028 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192029
2030 MockRead data_reads[] = {
2031 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432032 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192033 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422034 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192035 };
[email protected]31a2bfe2010-02-09 08:03:392036 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592037 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192038
2039 TestCompletionCallback callback;
2040
[email protected]684970b2009-08-14 04:54:462041 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422042 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192043
2044 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422045 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192046
[email protected]1c773ea12009-04-28 19:58:422047 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192048 EXPECT_TRUE(response == NULL);
2049}
[email protected]f4e426b2008-11-05 00:24:492050
2051// Make sure that we don't try to reuse a TCPClientSocket when failing to
2052// establish tunnel.
2053// http://code.google.com/p/chromium/issues/detail?id=3772
2054TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2055 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592056 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012057
[email protected]228ff742009-06-05 01:19:592058 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492059
[email protected]5695b8c2009-09-30 21:36:432060 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492061
[email protected]1c773ea12009-04-28 19:58:422062 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492063 request.method = "GET";
2064 request.url = GURL("https://www.google.com/");
2065 request.load_flags = 0;
2066
2067 // Since we have proxy, should try to establish tunnel.
2068 MockWrite data_writes1[] = {
2069 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452070 "Host: www.google.com\r\n"
2071 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492072 };
2073
[email protected]77848d12008-11-14 00:00:222074 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492075 // connection. Usually a proxy would return 501 (not implemented),
2076 // or 200 (tunnel established).
2077 MockRead data_reads1[] = {
2078 MockRead("HTTP/1.1 404 Not Found\r\n"),
2079 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422080 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492081 };
2082
[email protected]31a2bfe2010-02-09 08:03:392083 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2084 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592085 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492086
2087 TestCompletionCallback callback1;
2088
[email protected]684970b2009-08-14 04:54:462089 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422090 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492091
2092 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422093 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492094
[email protected]1c773ea12009-04-28 19:58:422095 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082096 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492097
[email protected]b4404c02009-04-10 16:38:522098 // Empty the current queue. This is necessary because idle sockets are
2099 // added to the connection pool asynchronously with a PostTask.
2100 MessageLoop::current()->RunAllPending();
2101
[email protected]f4e426b2008-11-05 00:24:492102 // We now check to make sure the TCPClientSocket was not added back to
2103 // the pool.
[email protected]a937a06d2009-08-19 21:19:242104 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492105 trans.reset();
[email protected]b4404c02009-04-10 16:38:522106 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492107 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242108 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492109}
[email protected]372d34a2008-11-05 21:30:512110
[email protected]1b157c02009-04-21 01:55:402111// Make sure that we recycle a socket after reading all of the response body.
2112TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592113 SessionDependencies session_deps;
2114 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402115
[email protected]5695b8c2009-09-30 21:36:432116 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402117
[email protected]1c773ea12009-04-28 19:58:422118 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402119 request.method = "GET";
2120 request.url = GURL("http://www.google.com/");
2121 request.load_flags = 0;
2122
2123 MockRead data_reads[] = {
2124 // A part of the response body is received with the response headers.
2125 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2126 // The rest of the response body is received in two parts.
2127 MockRead("lo"),
2128 MockRead(" world"),
2129 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422130 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402131 };
2132
[email protected]31a2bfe2010-02-09 08:03:392133 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592134 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402135
2136 TestCompletionCallback callback;
2137
[email protected]684970b2009-08-14 04:54:462138 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422139 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402140
2141 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422142 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402143
[email protected]1c773ea12009-04-28 19:58:422144 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402145 EXPECT_TRUE(response != NULL);
2146
2147 EXPECT_TRUE(response->headers != NULL);
2148 std::string status_line = response->headers->GetStatusLine();
2149 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2150
[email protected]a937a06d2009-08-19 21:19:242151 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402152
2153 std::string response_data;
2154 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422155 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402156 EXPECT_EQ("hello world", response_data);
2157
2158 // Empty the current queue. This is necessary because idle sockets are
2159 // added to the connection pool asynchronously with a PostTask.
2160 MessageLoop::current()->RunAllPending();
2161
2162 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242163 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402164}
2165
[email protected]b4404c02009-04-10 16:38:522166// Make sure that we recycle a socket after a zero-length response.
2167// http://crbug.com/9880
2168TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592169 SessionDependencies session_deps;
2170 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522171
[email protected]5695b8c2009-09-30 21:36:432172 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522173
[email protected]1c773ea12009-04-28 19:58:422174 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522175 request.method = "GET";
2176 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2177 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2178 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2179 "rt=prt.2642,ol.2649,xjs.2951");
2180 request.load_flags = 0;
2181
2182 MockRead data_reads[] = {
2183 MockRead("HTTP/1.1 204 No Content\r\n"
2184 "Content-Length: 0\r\n"
2185 "Content-Type: text/html\r\n\r\n"),
2186 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422187 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522188 };
2189
[email protected]31a2bfe2010-02-09 08:03:392190 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592191 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522192
2193 TestCompletionCallback callback;
2194
[email protected]684970b2009-08-14 04:54:462195 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422196 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522197
2198 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422199 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522200
[email protected]1c773ea12009-04-28 19:58:422201 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522202 EXPECT_TRUE(response != NULL);
2203
2204 EXPECT_TRUE(response->headers != NULL);
2205 std::string status_line = response->headers->GetStatusLine();
2206 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2207
[email protected]a937a06d2009-08-19 21:19:242208 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522209
2210 std::string response_data;
2211 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422212 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522213 EXPECT_EQ("", response_data);
2214
2215 // Empty the current queue. This is necessary because idle sockets are
2216 // added to the connection pool asynchronously with a PostTask.
2217 MessageLoop::current()->RunAllPending();
2218
2219 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242220 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522221}
2222
[email protected]372d34a2008-11-05 21:30:512223TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422224 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512225 // Transaction 1: a GET request that succeeds. The socket is recycled
2226 // after use.
2227 request[0].method = "GET";
2228 request[0].url = GURL("http://www.google.com/");
2229 request[0].load_flags = 0;
2230 // Transaction 2: a POST request. Reuses the socket kept alive from
2231 // transaction 1. The first attempts fails when writing the POST data.
2232 // This causes the transaction to retry with a new socket. The second
2233 // attempt succeeds.
2234 request[1].method = "POST";
2235 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422236 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512237 request[1].upload_data->AppendBytes("foo", 3);
2238 request[1].load_flags = 0;
2239
[email protected]228ff742009-06-05 01:19:592240 SessionDependencies session_deps;
2241 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512242
2243 // The first socket is used for transaction 1 and the first attempt of
2244 // transaction 2.
2245
2246 // The response of transaction 1.
2247 MockRead data_reads1[] = {
2248 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2249 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422250 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512251 };
2252 // The mock write results of transaction 1 and the first attempt of
2253 // transaction 2.
2254 MockWrite data_writes1[] = {
2255 MockWrite(false, 64), // GET
2256 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422257 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512258 };
[email protected]31a2bfe2010-02-09 08:03:392259 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2260 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512261
2262 // The second socket is used for the second attempt of transaction 2.
2263
2264 // The response of transaction 2.
2265 MockRead data_reads2[] = {
2266 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2267 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422268 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512269 };
2270 // The mock write results of the second attempt of transaction 2.
2271 MockWrite data_writes2[] = {
2272 MockWrite(false, 93), // POST
2273 MockWrite(false, 3), // POST data
2274 };
[email protected]31a2bfe2010-02-09 08:03:392275 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2276 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512277
[email protected]5ecc992a42009-11-11 01:41:592278 session_deps.socket_factory.AddSocketDataProvider(&data1);
2279 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512280
2281 const char* kExpectedResponseData[] = {
2282 "hello world", "welcome"
2283 };
2284
2285 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422286 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432287 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512288
2289 TestCompletionCallback callback;
2290
[email protected]684970b2009-08-14 04:54:462291 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422292 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512293
2294 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422295 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512296
[email protected]1c773ea12009-04-28 19:58:422297 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512298 EXPECT_TRUE(response != NULL);
2299
2300 EXPECT_TRUE(response->headers != NULL);
2301 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2302
2303 std::string response_data;
2304 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422305 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512306 EXPECT_EQ(kExpectedResponseData[i], response_data);
2307 }
2308}
[email protected]f9ee6b52008-11-08 06:46:232309
2310// Test the request-challenge-retry sequence for basic auth when there is
2311// an identity in the URL. The request should be sent as normal, but when
2312// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322313TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592314 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402315 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432316 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232317
[email protected]1c773ea12009-04-28 19:58:422318 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232319 request.method = "GET";
2320 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292321 request.url = GURL("http://foo:b@[email protected]/");
2322
2323 // The password contains an escaped character -- for this test to pass it
2324 // will need to be unescaped by HttpNetworkTransaction.
2325 EXPECT_EQ("b%40r", request.url.password());
2326
[email protected]ea9dc9a2009-09-05 00:43:322327 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232328
2329 MockWrite data_writes1[] = {
2330 MockWrite("GET / HTTP/1.1\r\n"
2331 "Host: www.google.com\r\n"
2332 "Connection: keep-alive\r\n\r\n"),
2333 };
2334
2335 MockRead data_reads1[] = {
2336 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2337 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2338 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422339 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232340 };
2341
2342 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322343 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232344 MockWrite data_writes2[] = {
2345 MockWrite("GET / HTTP/1.1\r\n"
2346 "Host: www.google.com\r\n"
2347 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292348 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232349 };
2350
2351 MockRead data_reads2[] = {
2352 MockRead("HTTP/1.0 200 OK\r\n"),
2353 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422354 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232355 };
2356
[email protected]31a2bfe2010-02-09 08:03:392357 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2358 data_writes1, arraysize(data_writes1));
2359 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2360 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592361 session_deps.socket_factory.AddSocketDataProvider(&data1);
2362 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232363
2364 TestCompletionCallback callback1;
2365
[email protected]684970b2009-08-14 04:54:462366 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422367 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232368
2369 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422370 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232371
[email protected]0757e7702009-03-27 04:00:222372 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2373 TestCompletionCallback callback2;
2374 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422375 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222376 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422377 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222378 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2379
[email protected]1c773ea12009-04-28 19:58:422380 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232381 EXPECT_FALSE(response == NULL);
2382
2383 // There is no challenge info, since the identity in URL worked.
2384 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2385
2386 EXPECT_EQ(100, response->headers->GetContentLength());
2387
2388 // Empty the current queue.
2389 MessageLoop::current()->RunAllPending();
2390}
2391
[email protected]ea9dc9a2009-09-05 00:43:322392// Test the request-challenge-retry sequence for basic auth when there is
2393// an incorrect identity in the URL. The identity from the URL should be used
2394// only once.
2395TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2396 SessionDependencies session_deps;
2397 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432398 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322399
2400 HttpRequestInfo request;
2401 request.method = "GET";
2402 // Note: the URL has a username:password in it. The password "baz" is
2403 // wrong (should be "bar").
2404 request.url = GURL("http://foo:[email protected]/");
2405
2406 request.load_flags = LOAD_NORMAL;
2407
2408 MockWrite data_writes1[] = {
2409 MockWrite("GET / HTTP/1.1\r\n"
2410 "Host: www.google.com\r\n"
2411 "Connection: keep-alive\r\n\r\n"),
2412 };
2413
2414 MockRead data_reads1[] = {
2415 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2416 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2417 MockRead("Content-Length: 10\r\n\r\n"),
2418 MockRead(false, ERR_FAILED),
2419 };
2420
2421 // After the challenge above, the transaction will be restarted using the
2422 // identity from the url (foo, baz) to answer the challenge.
2423 MockWrite data_writes2[] = {
2424 MockWrite("GET / HTTP/1.1\r\n"
2425 "Host: www.google.com\r\n"
2426 "Connection: keep-alive\r\n"
2427 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2428 };
2429
2430 MockRead data_reads2[] = {
2431 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2432 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2433 MockRead("Content-Length: 10\r\n\r\n"),
2434 MockRead(false, ERR_FAILED),
2435 };
2436
2437 // After the challenge above, the transaction will be restarted using the
2438 // identity supplied by the user (foo, bar) to answer the challenge.
2439 MockWrite data_writes3[] = {
2440 MockWrite("GET / HTTP/1.1\r\n"
2441 "Host: www.google.com\r\n"
2442 "Connection: keep-alive\r\n"
2443 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2444 };
2445
2446 MockRead data_reads3[] = {
2447 MockRead("HTTP/1.0 200 OK\r\n"),
2448 MockRead("Content-Length: 100\r\n\r\n"),
2449 MockRead(false, OK),
2450 };
2451
[email protected]31a2bfe2010-02-09 08:03:392452 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2453 data_writes1, arraysize(data_writes1));
2454 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2455 data_writes2, arraysize(data_writes2));
2456 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2457 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592458 session_deps.socket_factory.AddSocketDataProvider(&data1);
2459 session_deps.socket_factory.AddSocketDataProvider(&data2);
2460 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322461
2462 TestCompletionCallback callback1;
2463
2464 int rv = trans->Start(&request, &callback1, NULL);
2465 EXPECT_EQ(ERR_IO_PENDING, rv);
2466
2467 rv = callback1.WaitForResult();
2468 EXPECT_EQ(OK, rv);
2469
2470 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2471 TestCompletionCallback callback2;
2472 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2473 EXPECT_EQ(ERR_IO_PENDING, rv);
2474 rv = callback2.WaitForResult();
2475 EXPECT_EQ(OK, rv);
2476 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2477
2478 const HttpResponseInfo* response = trans->GetResponseInfo();
2479 EXPECT_FALSE(response == NULL);
2480 // The password prompt info should have been set in response->auth_challenge.
2481 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2482
2483 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2484 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2485 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2486
2487 TestCompletionCallback callback3;
2488 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2489 EXPECT_EQ(ERR_IO_PENDING, rv);
2490 rv = callback3.WaitForResult();
2491 EXPECT_EQ(OK, rv);
2492 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2493
2494 response = trans->GetResponseInfo();
2495 EXPECT_FALSE(response == NULL);
2496
2497 // There is no challenge info, since the identity worked.
2498 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2499
2500 EXPECT_EQ(100, response->headers->GetContentLength());
2501
2502 // Empty the current queue.
2503 MessageLoop::current()->RunAllPending();
2504}
2505
[email protected]f9ee6b52008-11-08 06:46:232506// Test that previously tried username/passwords for a realm get re-used.
2507TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592508 SessionDependencies session_deps;
2509 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232510
2511 // Transaction 1: authenticate (foo, bar) on MyRealm1
2512 {
[email protected]5695b8c2009-09-30 21:36:432513 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232514
[email protected]1c773ea12009-04-28 19:58:422515 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232516 request.method = "GET";
2517 request.url = GURL("http://www.google.com/x/y/z");
2518 request.load_flags = 0;
2519
2520 MockWrite data_writes1[] = {
2521 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2522 "Host: www.google.com\r\n"
2523 "Connection: keep-alive\r\n\r\n"),
2524 };
2525
2526 MockRead data_reads1[] = {
2527 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2528 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2529 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422530 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232531 };
2532
2533 // Resend with authorization (username=foo, password=bar)
2534 MockWrite data_writes2[] = {
2535 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2536 "Host: www.google.com\r\n"
2537 "Connection: keep-alive\r\n"
2538 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2539 };
2540
2541 // Sever accepts the authorization.
2542 MockRead data_reads2[] = {
2543 MockRead("HTTP/1.0 200 OK\r\n"),
2544 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422545 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232546 };
2547
[email protected]31a2bfe2010-02-09 08:03:392548 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2549 data_writes1, arraysize(data_writes1));
2550 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2551 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592552 session_deps.socket_factory.AddSocketDataProvider(&data1);
2553 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232554
2555 TestCompletionCallback callback1;
2556
[email protected]684970b2009-08-14 04:54:462557 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422558 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232559
2560 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422561 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232562
[email protected]1c773ea12009-04-28 19:58:422563 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232564 EXPECT_FALSE(response == NULL);
2565
2566 // The password prompt info should have been set in
2567 // response->auth_challenge.
2568 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2569
[email protected]71e4573a2009-05-21 22:03:002570 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232571 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2572 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2573
2574 TestCompletionCallback callback2;
2575
2576 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422577 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232578
2579 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422580 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232581
2582 response = trans->GetResponseInfo();
2583 EXPECT_FALSE(response == NULL);
2584 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2585 EXPECT_EQ(100, response->headers->GetContentLength());
2586 }
2587
2588 // ------------------------------------------------------------------------
2589
2590 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2591 {
[email protected]5695b8c2009-09-30 21:36:432592 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232593
[email protected]1c773ea12009-04-28 19:58:422594 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232595 request.method = "GET";
2596 // Note that Transaction 1 was at /x/y/z, so this is in the same
2597 // protection space as MyRealm1.
2598 request.url = GURL("http://www.google.com/x/y/a/b");
2599 request.load_flags = 0;
2600
2601 MockWrite data_writes1[] = {
2602 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2603 "Host: www.google.com\r\n"
2604 "Connection: keep-alive\r\n"
2605 // Send preemptive authorization for MyRealm1
2606 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2607 };
2608
2609 // The server didn't like the preemptive authorization, and
2610 // challenges us for a different realm (MyRealm2).
2611 MockRead data_reads1[] = {
2612 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2613 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2614 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422615 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232616 };
2617
2618 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2619 MockWrite data_writes2[] = {
2620 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2621 "Host: www.google.com\r\n"
2622 "Connection: keep-alive\r\n"
2623 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2624 };
2625
2626 // Sever accepts the authorization.
2627 MockRead data_reads2[] = {
2628 MockRead("HTTP/1.0 200 OK\r\n"),
2629 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422630 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232631 };
2632
[email protected]31a2bfe2010-02-09 08:03:392633 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2634 data_writes1, arraysize(data_writes1));
2635 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2636 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592637 session_deps.socket_factory.AddSocketDataProvider(&data1);
2638 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232639
2640 TestCompletionCallback callback1;
2641
[email protected]684970b2009-08-14 04:54:462642 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422643 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232644
2645 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422646 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232647
[email protected]1c773ea12009-04-28 19:58:422648 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232649 EXPECT_FALSE(response == NULL);
2650
2651 // The password prompt info should have been set in
2652 // response->auth_challenge.
2653 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2654
[email protected]71e4573a2009-05-21 22:03:002655 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232656 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2657 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2658
2659 TestCompletionCallback callback2;
2660
2661 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422662 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232663
2664 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422665 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232666
2667 response = trans->GetResponseInfo();
2668 EXPECT_FALSE(response == NULL);
2669 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2670 EXPECT_EQ(100, response->headers->GetContentLength());
2671 }
2672
2673 // ------------------------------------------------------------------------
2674
2675 // Transaction 3: Resend a request in MyRealm's protection space --
2676 // succeed with preemptive authorization.
2677 {
[email protected]5695b8c2009-09-30 21:36:432678 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232679
[email protected]1c773ea12009-04-28 19:58:422680 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232681 request.method = "GET";
2682 request.url = GURL("http://www.google.com/x/y/z2");
2683 request.load_flags = 0;
2684
2685 MockWrite data_writes1[] = {
2686 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2687 "Host: www.google.com\r\n"
2688 "Connection: keep-alive\r\n"
2689 // The authorization for MyRealm1 gets sent preemptively
2690 // (since the url is in the same protection space)
2691 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2692 };
2693
2694 // Sever accepts the preemptive authorization
2695 MockRead data_reads1[] = {
2696 MockRead("HTTP/1.0 200 OK\r\n"),
2697 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422698 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232699 };
2700
[email protected]31a2bfe2010-02-09 08:03:392701 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2702 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592703 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232704
2705 TestCompletionCallback callback1;
2706
[email protected]684970b2009-08-14 04:54:462707 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422708 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232709
2710 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422711 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232712
[email protected]1c773ea12009-04-28 19:58:422713 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232714 EXPECT_FALSE(response == NULL);
2715
2716 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2717 EXPECT_EQ(100, response->headers->GetContentLength());
2718 }
2719
2720 // ------------------------------------------------------------------------
2721
2722 // Transaction 4: request another URL in MyRealm (however the
2723 // url is not known to belong to the protection space, so no pre-auth).
2724 {
[email protected]5695b8c2009-09-30 21:36:432725 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232726
[email protected]1c773ea12009-04-28 19:58:422727 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232728 request.method = "GET";
2729 request.url = GURL("http://www.google.com/x/1");
2730 request.load_flags = 0;
2731
2732 MockWrite data_writes1[] = {
2733 MockWrite("GET /x/1 HTTP/1.1\r\n"
2734 "Host: www.google.com\r\n"
2735 "Connection: keep-alive\r\n\r\n"),
2736 };
2737
2738 MockRead data_reads1[] = {
2739 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2740 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2741 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422742 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232743 };
2744
2745 // Resend with authorization from MyRealm's cache.
2746 MockWrite data_writes2[] = {
2747 MockWrite("GET /x/1 HTTP/1.1\r\n"
2748 "Host: www.google.com\r\n"
2749 "Connection: keep-alive\r\n"
2750 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2751 };
2752
2753 // Sever accepts the authorization.
2754 MockRead data_reads2[] = {
2755 MockRead("HTTP/1.0 200 OK\r\n"),
2756 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422757 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232758 };
2759
[email protected]31a2bfe2010-02-09 08:03:392760 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2761 data_writes1, arraysize(data_writes1));
2762 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2763 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592764 session_deps.socket_factory.AddSocketDataProvider(&data1);
2765 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232766
2767 TestCompletionCallback callback1;
2768
[email protected]684970b2009-08-14 04:54:462769 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422770 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232771
2772 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422773 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232774
[email protected]0757e7702009-03-27 04:00:222775 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2776 TestCompletionCallback callback2;
2777 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422778 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222779 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422780 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222781 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2782
[email protected]1c773ea12009-04-28 19:58:422783 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232784 EXPECT_FALSE(response == NULL);
2785 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2786 EXPECT_EQ(100, response->headers->GetContentLength());
2787 }
2788
2789 // ------------------------------------------------------------------------
2790
2791 // Transaction 5: request a URL in MyRealm, but the server rejects the
2792 // cached identity. Should invalidate and re-prompt.
2793 {
[email protected]5695b8c2009-09-30 21:36:432794 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232795
[email protected]1c773ea12009-04-28 19:58:422796 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232797 request.method = "GET";
2798 request.url = GURL("http://www.google.com/p/q/t");
2799 request.load_flags = 0;
2800
2801 MockWrite data_writes1[] = {
2802 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2803 "Host: www.google.com\r\n"
2804 "Connection: keep-alive\r\n\r\n"),
2805 };
2806
2807 MockRead data_reads1[] = {
2808 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2809 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2810 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422811 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232812 };
2813
2814 // Resend with authorization from cache for MyRealm.
2815 MockWrite data_writes2[] = {
2816 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2817 "Host: www.google.com\r\n"
2818 "Connection: keep-alive\r\n"
2819 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2820 };
2821
2822 // Sever rejects the authorization.
2823 MockRead data_reads2[] = {
2824 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2825 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2826 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422827 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232828 };
2829
2830 // At this point we should prompt for new credentials for MyRealm.
2831 // Restart with username=foo3, password=foo4.
2832 MockWrite data_writes3[] = {
2833 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2834 "Host: www.google.com\r\n"
2835 "Connection: keep-alive\r\n"
2836 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2837 };
2838
2839 // Sever accepts the authorization.
2840 MockRead data_reads3[] = {
2841 MockRead("HTTP/1.0 200 OK\r\n"),
2842 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422843 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232844 };
2845
[email protected]31a2bfe2010-02-09 08:03:392846 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2847 data_writes1, arraysize(data_writes1));
2848 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2849 data_writes2, arraysize(data_writes2));
2850 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2851 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592852 session_deps.socket_factory.AddSocketDataProvider(&data1);
2853 session_deps.socket_factory.AddSocketDataProvider(&data2);
2854 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232855
2856 TestCompletionCallback callback1;
2857
[email protected]684970b2009-08-14 04:54:462858 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422859 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232860
2861 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422862 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232863
[email protected]0757e7702009-03-27 04:00:222864 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2865 TestCompletionCallback callback2;
2866 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422867 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222868 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422869 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222870 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2871
[email protected]1c773ea12009-04-28 19:58:422872 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232873 EXPECT_FALSE(response == NULL);
2874
2875 // The password prompt info should have been set in
2876 // response->auth_challenge.
2877 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2878
[email protected]71e4573a2009-05-21 22:03:002879 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232880 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2881 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2882
[email protected]0757e7702009-03-27 04:00:222883 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232884
[email protected]0757e7702009-03-27 04:00:222885 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422886 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232887
[email protected]0757e7702009-03-27 04:00:222888 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422889 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232890
2891 response = trans->GetResponseInfo();
2892 EXPECT_FALSE(response == NULL);
2893 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2894 EXPECT_EQ(100, response->headers->GetContentLength());
2895 }
2896}
[email protected]89ceba9a2009-03-21 03:46:062897
2898// Test the ResetStateForRestart() private method.
2899TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2900 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592901 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402902 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432903 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062904
2905 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062906 trans->read_buf_ = new IOBuffer(15);
2907 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572908 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062909
2910 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:142911 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:572912 response->auth_challenge = new AuthChallengeInfo();
2913 response->ssl_info.cert_status = -15;
2914 response->response_time = base::Time::Now();
2915 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062916
2917 { // Setup state for response_.vary_data
2918 HttpRequestInfo request;
2919 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2920 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:572921 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]89ceba9a2009-03-21 03:46:062922 request.extra_headers = "Foo: 1\nbar: 23";
[email protected]0877e3d2009-10-17 22:29:572923 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:062924 }
2925
2926 // Cause the above state to be reset.
2927 trans->ResetStateForRestart();
2928
2929 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:072930 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:062931 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:572932 EXPECT_EQ(0U, trans->request_headers_.size());
2933 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2934 EXPECT_TRUE(response->headers.get() == NULL);
2935 EXPECT_EQ(false, response->was_cached);
2936 EXPECT_EQ(0, response->ssl_info.cert_status);
2937 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:062938}
2939
[email protected]bacff652009-03-31 17:50:332940// Test HTTPS connections to a site with a bad certificate
2941TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592942 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402943 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432944 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332945
2946 HttpRequestInfo request;
2947 request.method = "GET";
2948 request.url = GURL("https://www.google.com/");
2949 request.load_flags = 0;
2950
2951 MockWrite data_writes[] = {
2952 MockWrite("GET / HTTP/1.1\r\n"
2953 "Host: www.google.com\r\n"
2954 "Connection: keep-alive\r\n\r\n"),
2955 };
2956
2957 MockRead data_reads[] = {
2958 MockRead("HTTP/1.0 200 OK\r\n"),
2959 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2960 MockRead("Content-Length: 100\r\n\r\n"),
2961 MockRead(false, OK),
2962 };
2963
[email protected]5ecc992a42009-11-11 01:41:592964 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:392965 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2966 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592967 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2968 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:332969
[email protected]5ecc992a42009-11-11 01:41:592970 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2971 session_deps.socket_factory.AddSocketDataProvider(&data);
2972 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2973 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:332974
2975 TestCompletionCallback callback;
2976
[email protected]684970b2009-08-14 04:54:462977 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332978 EXPECT_EQ(ERR_IO_PENDING, rv);
2979
2980 rv = callback.WaitForResult();
2981 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2982
2983 rv = trans->RestartIgnoringLastError(&callback);
2984 EXPECT_EQ(ERR_IO_PENDING, rv);
2985
2986 rv = callback.WaitForResult();
2987 EXPECT_EQ(OK, rv);
2988
2989 const HttpResponseInfo* response = trans->GetResponseInfo();
2990
2991 EXPECT_FALSE(response == NULL);
2992 EXPECT_EQ(100, response->headers->GetContentLength());
2993}
2994
2995// Test HTTPS connections to a site with a bad certificate, going through a
2996// proxy
2997TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592998 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332999
3000 HttpRequestInfo request;
3001 request.method = "GET";
3002 request.url = GURL("https://www.google.com/");
3003 request.load_flags = 0;
3004
3005 MockWrite proxy_writes[] = {
3006 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453007 "Host: www.google.com\r\n"
3008 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333009 };
3010
3011 MockRead proxy_reads[] = {
3012 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423013 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333014 };
3015
3016 MockWrite data_writes[] = {
3017 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453018 "Host: www.google.com\r\n"
3019 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333020 MockWrite("GET / HTTP/1.1\r\n"
3021 "Host: www.google.com\r\n"
3022 "Connection: keep-alive\r\n\r\n"),
3023 };
3024
3025 MockRead data_reads[] = {
3026 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3027 MockRead("HTTP/1.0 200 OK\r\n"),
3028 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3029 MockRead("Content-Length: 100\r\n\r\n"),
3030 MockRead(false, OK),
3031 };
3032
[email protected]31a2bfe2010-02-09 08:03:393033 StaticSocketDataProvider ssl_bad_certificate(
3034 proxy_reads, arraysize(proxy_reads),
3035 proxy_writes, arraysize(proxy_writes));
3036 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3037 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593038 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3039 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333040
[email protected]5ecc992a42009-11-11 01:41:593041 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3042 session_deps.socket_factory.AddSocketDataProvider(&data);
3043 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3044 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333045
3046 TestCompletionCallback callback;
3047
3048 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593049 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333050
[email protected]d207a5f2009-06-04 05:28:403051 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433052 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333053
[email protected]684970b2009-08-14 04:54:463054 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:333055 EXPECT_EQ(ERR_IO_PENDING, rv);
3056
3057 rv = callback.WaitForResult();
3058 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3059
3060 rv = trans->RestartIgnoringLastError(&callback);
3061 EXPECT_EQ(ERR_IO_PENDING, rv);
3062
3063 rv = callback.WaitForResult();
3064 EXPECT_EQ(OK, rv);
3065
3066 const HttpResponseInfo* response = trans->GetResponseInfo();
3067
3068 EXPECT_FALSE(response == NULL);
3069 EXPECT_EQ(100, response->headers->GetContentLength());
3070 }
3071}
3072
[email protected]1c773ea12009-04-28 19:58:423073TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593074 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403075 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433076 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423077
3078 HttpRequestInfo request;
3079 request.method = "GET";
3080 request.url = GURL("http://www.google.com/");
3081 request.user_agent = "Chromium Ultra Awesome X Edition";
3082
3083 MockWrite data_writes[] = {
3084 MockWrite("GET / HTTP/1.1\r\n"
3085 "Host: www.google.com\r\n"
3086 "Connection: keep-alive\r\n"
3087 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3088 };
3089
3090 // Lastly, the server responds with the actual content.
3091 MockRead data_reads[] = {
3092 MockRead("HTTP/1.0 200 OK\r\n"),
3093 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3094 MockRead("Content-Length: 100\r\n\r\n"),
3095 MockRead(false, OK),
3096 };
3097
[email protected]31a2bfe2010-02-09 08:03:393098 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3099 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593100 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423101
3102 TestCompletionCallback callback;
3103
[email protected]684970b2009-08-14 04:54:463104 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423105 EXPECT_EQ(ERR_IO_PENDING, rv);
3106
3107 rv = callback.WaitForResult();
3108 EXPECT_EQ(OK, rv);
3109}
3110
3111TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593112 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403113 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433114 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423115
3116 HttpRequestInfo request;
3117 request.method = "GET";
3118 request.url = GURL("http://www.google.com/");
3119 request.load_flags = 0;
3120 request.referrer = GURL("http://the.previous.site.com/");
3121
3122 MockWrite data_writes[] = {
3123 MockWrite("GET / HTTP/1.1\r\n"
3124 "Host: www.google.com\r\n"
3125 "Connection: keep-alive\r\n"
3126 "Referer: http://the.previous.site.com/\r\n\r\n"),
3127 };
3128
3129 // Lastly, the server responds with the actual content.
3130 MockRead data_reads[] = {
3131 MockRead("HTTP/1.0 200 OK\r\n"),
3132 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3133 MockRead("Content-Length: 100\r\n\r\n"),
3134 MockRead(false, OK),
3135 };
3136
[email protected]31a2bfe2010-02-09 08:03:393137 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3138 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593139 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423140
3141 TestCompletionCallback callback;
3142
[email protected]684970b2009-08-14 04:54:463143 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423144 EXPECT_EQ(ERR_IO_PENDING, rv);
3145
3146 rv = callback.WaitForResult();
3147 EXPECT_EQ(OK, rv);
3148}
3149
3150TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593151 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403152 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433153 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423154
3155 HttpRequestInfo request;
3156 request.method = "POST";
3157 request.url = GURL("http://www.google.com/");
3158
3159 MockWrite data_writes[] = {
3160 MockWrite("POST / HTTP/1.1\r\n"
3161 "Host: www.google.com\r\n"
3162 "Connection: keep-alive\r\n"
3163 "Content-Length: 0\r\n\r\n"),
3164 };
3165
3166 // Lastly, the server responds with the actual content.
3167 MockRead data_reads[] = {
3168 MockRead("HTTP/1.0 200 OK\r\n"),
3169 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3170 MockRead("Content-Length: 100\r\n\r\n"),
3171 MockRead(false, OK),
3172 };
3173
[email protected]31a2bfe2010-02-09 08:03:393174 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3175 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593176 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423177
3178 TestCompletionCallback callback;
3179
[email protected]684970b2009-08-14 04:54:463180 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423181 EXPECT_EQ(ERR_IO_PENDING, rv);
3182
3183 rv = callback.WaitForResult();
3184 EXPECT_EQ(OK, rv);
3185}
3186
3187TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593188 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403189 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433190 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423191
3192 HttpRequestInfo request;
3193 request.method = "PUT";
3194 request.url = GURL("http://www.google.com/");
3195
3196 MockWrite data_writes[] = {
3197 MockWrite("PUT / HTTP/1.1\r\n"
3198 "Host: www.google.com\r\n"
3199 "Connection: keep-alive\r\n"
3200 "Content-Length: 0\r\n\r\n"),
3201 };
3202
3203 // Lastly, the server responds with the actual content.
3204 MockRead data_reads[] = {
3205 MockRead("HTTP/1.0 200 OK\r\n"),
3206 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3207 MockRead("Content-Length: 100\r\n\r\n"),
3208 MockRead(false, OK),
3209 };
3210
[email protected]31a2bfe2010-02-09 08:03:393211 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3212 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593213 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423214
3215 TestCompletionCallback callback;
3216
[email protected]684970b2009-08-14 04:54:463217 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423218 EXPECT_EQ(ERR_IO_PENDING, rv);
3219
3220 rv = callback.WaitForResult();
3221 EXPECT_EQ(OK, rv);
3222}
3223
3224TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593225 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403226 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433227 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423228
3229 HttpRequestInfo request;
3230 request.method = "HEAD";
3231 request.url = GURL("http://www.google.com/");
3232
3233 MockWrite data_writes[] = {
3234 MockWrite("HEAD / HTTP/1.1\r\n"
3235 "Host: www.google.com\r\n"
3236 "Connection: keep-alive\r\n"
3237 "Content-Length: 0\r\n\r\n"),
3238 };
3239
3240 // Lastly, the server responds with the actual content.
3241 MockRead data_reads[] = {
3242 MockRead("HTTP/1.0 200 OK\r\n"),
3243 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3244 MockRead("Content-Length: 100\r\n\r\n"),
3245 MockRead(false, OK),
3246 };
3247
[email protected]31a2bfe2010-02-09 08:03:393248 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3249 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593250 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423251
3252 TestCompletionCallback callback;
3253
[email protected]684970b2009-08-14 04:54:463254 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423255 EXPECT_EQ(ERR_IO_PENDING, rv);
3256
3257 rv = callback.WaitForResult();
3258 EXPECT_EQ(OK, rv);
3259}
3260
3261TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593262 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403263 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433264 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423265
3266 HttpRequestInfo request;
3267 request.method = "GET";
3268 request.url = GURL("http://www.google.com/");
3269 request.load_flags = LOAD_BYPASS_CACHE;
3270
3271 MockWrite data_writes[] = {
3272 MockWrite("GET / HTTP/1.1\r\n"
3273 "Host: www.google.com\r\n"
3274 "Connection: keep-alive\r\n"
3275 "Pragma: no-cache\r\n"
3276 "Cache-Control: no-cache\r\n\r\n"),
3277 };
3278
3279 // Lastly, the server responds with the actual content.
3280 MockRead data_reads[] = {
3281 MockRead("HTTP/1.0 200 OK\r\n"),
3282 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3283 MockRead("Content-Length: 100\r\n\r\n"),
3284 MockRead(false, OK),
3285 };
3286
[email protected]31a2bfe2010-02-09 08:03:393287 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3288 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593289 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423290
3291 TestCompletionCallback callback;
3292
[email protected]684970b2009-08-14 04:54:463293 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423294 EXPECT_EQ(ERR_IO_PENDING, rv);
3295
3296 rv = callback.WaitForResult();
3297 EXPECT_EQ(OK, rv);
3298}
3299
3300TEST_F(HttpNetworkTransactionTest,
3301 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593302 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403303 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433304 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423305
3306 HttpRequestInfo request;
3307 request.method = "GET";
3308 request.url = GURL("http://www.google.com/");
3309 request.load_flags = LOAD_VALIDATE_CACHE;
3310
3311 MockWrite data_writes[] = {
3312 MockWrite("GET / HTTP/1.1\r\n"
3313 "Host: www.google.com\r\n"
3314 "Connection: keep-alive\r\n"
3315 "Cache-Control: max-age=0\r\n\r\n"),
3316 };
3317
3318 // Lastly, the server responds with the actual content.
3319 MockRead data_reads[] = {
3320 MockRead("HTTP/1.0 200 OK\r\n"),
3321 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3322 MockRead("Content-Length: 100\r\n\r\n"),
3323 MockRead(false, OK),
3324 };
3325
[email protected]31a2bfe2010-02-09 08:03:393326 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3327 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593328 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423329
3330 TestCompletionCallback callback;
3331
[email protected]684970b2009-08-14 04:54:463332 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423333 EXPECT_EQ(ERR_IO_PENDING, rv);
3334
3335 rv = callback.WaitForResult();
3336 EXPECT_EQ(OK, rv);
3337}
3338
3339TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593340 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403341 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433342 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423343
3344 HttpRequestInfo request;
3345 request.method = "GET";
3346 request.url = GURL("http://www.google.com/");
3347 request.extra_headers = "FooHeader: Bar\r\n";
3348
3349 MockWrite data_writes[] = {
3350 MockWrite("GET / HTTP/1.1\r\n"
3351 "Host: www.google.com\r\n"
3352 "Connection: keep-alive\r\n"
3353 "FooHeader: Bar\r\n\r\n"),
3354 };
3355
3356 // Lastly, the server responds with the actual content.
3357 MockRead data_reads[] = {
3358 MockRead("HTTP/1.0 200 OK\r\n"),
3359 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3360 MockRead("Content-Length: 100\r\n\r\n"),
3361 MockRead(false, OK),
3362 };
3363
[email protected]31a2bfe2010-02-09 08:03:393364 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3365 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593366 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423367
3368 TestCompletionCallback callback;
3369
[email protected]684970b2009-08-14 04:54:463370 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423371 EXPECT_EQ(ERR_IO_PENDING, rv);
3372
3373 rv = callback.WaitForResult();
3374 EXPECT_EQ(OK, rv);
3375}
3376
[email protected]270c6412010-03-29 22:02:473377TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3378 SessionDependencies session_deps;
3379 scoped_ptr<HttpTransaction> trans(
3380 new HttpNetworkTransaction(CreateSession(&session_deps)));
3381
3382 HttpRequestInfo request;
3383 request.method = "GET";
3384 request.url = GURL("http://www.google.com/");
3385 request.extra_headers = "referer: www.foo.com\nhEllo: Kitty\rFoO: bar\r\n";
3386
3387 MockWrite data_writes[] = {
3388 MockWrite("GET / HTTP/1.1\r\n"
3389 "Host: www.google.com\r\n"
3390 "Connection: keep-alive\r\n"
3391 "hEllo: Kitty\r\n"
3392 "FoO: bar\r\n\r\n"),
3393 };
3394
3395 // Lastly, the server responds with the actual content.
3396 MockRead data_reads[] = {
3397 MockRead("HTTP/1.0 200 OK\r\n"),
3398 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3399 MockRead("Content-Length: 100\r\n\r\n"),
3400 MockRead(false, OK),
3401 };
3402
3403 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3404 data_writes, arraysize(data_writes));
3405 session_deps.socket_factory.AddSocketDataProvider(&data);
3406
3407 TestCompletionCallback callback;
3408
3409 int rv = trans->Start(&request, &callback, NULL);
3410 EXPECT_EQ(ERR_IO_PENDING, rv);
3411
3412 rv = callback.WaitForResult();
3413 EXPECT_EQ(OK, rv);
3414}
3415
[email protected]3cd17242009-06-23 02:59:023416TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093417 SessionDependencies session_deps(
3418 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023419
3420 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433421 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023422
3423 HttpRequestInfo request;
3424 request.method = "GET";
3425 request.url = GURL("http://www.google.com/");
3426 request.load_flags = 0;
3427
3428 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3429 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3430
3431 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353432 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023433 MockWrite("GET / HTTP/1.1\r\n"
3434 "Host: www.google.com\r\n"
3435 "Connection: keep-alive\r\n\r\n")
3436 };
3437
3438 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593439 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023440 MockRead("HTTP/1.0 200 OK\r\n"),
3441 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3442 MockRead("Payload"),
3443 MockRead(false, OK)
3444 };
3445
[email protected]31a2bfe2010-02-09 08:03:393446 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3447 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593448 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023449
3450 TestCompletionCallback callback;
3451
[email protected]684970b2009-08-14 04:54:463452 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023453 EXPECT_EQ(ERR_IO_PENDING, rv);
3454
3455 rv = callback.WaitForResult();
3456 EXPECT_EQ(OK, rv);
3457
3458 const HttpResponseInfo* response = trans->GetResponseInfo();
3459 EXPECT_FALSE(response == NULL);
3460
3461 std::string response_text;
3462 rv = ReadTransaction(trans.get(), &response_text);
3463 EXPECT_EQ(OK, rv);
3464 EXPECT_EQ("Payload", response_text);
3465}
3466
3467TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093468 SessionDependencies session_deps(
3469 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023470
3471 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433472 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023473
3474 HttpRequestInfo request;
3475 request.method = "GET";
3476 request.url = GURL("https://www.google.com/");
3477 request.load_flags = 0;
3478
3479 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3480 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3481
3482 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353483 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3484 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023485 MockWrite("GET / HTTP/1.1\r\n"
3486 "Host: www.google.com\r\n"
3487 "Connection: keep-alive\r\n\r\n")
3488 };
3489
3490 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353491 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3492 arraysize(read_buffer)),
3493 MockRead("HTTP/1.0 200 OK\r\n"),
3494 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3495 MockRead("Payload"),
3496 MockRead(false, OK)
3497 };
3498
[email protected]31a2bfe2010-02-09 08:03:393499 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3500 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593501 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353502
[email protected]5ecc992a42009-11-11 01:41:593503 SSLSocketDataProvider ssl(true, OK);
3504 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353505
3506 TestCompletionCallback callback;
3507
[email protected]684970b2009-08-14 04:54:463508 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353509 EXPECT_EQ(ERR_IO_PENDING, rv);
3510
3511 rv = callback.WaitForResult();
3512 EXPECT_EQ(OK, rv);
3513
3514 const HttpResponseInfo* response = trans->GetResponseInfo();
3515 EXPECT_FALSE(response == NULL);
3516
3517 std::string response_text;
3518 rv = ReadTransaction(trans.get(), &response_text);
3519 EXPECT_EQ(OK, rv);
3520 EXPECT_EQ("Payload", response_text);
3521}
3522
3523TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093524 SessionDependencies session_deps(
3525 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353526
3527 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433528 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353529
3530 HttpRequestInfo request;
3531 request.method = "GET";
3532 request.url = GURL("http://www.google.com/");
3533 request.load_flags = 0;
3534
3535 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3536 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373537 const char kSOCKS5OkRequest[] = {
3538 0x05, // Version
3539 0x01, // Command (CONNECT)
3540 0x00, // Reserved.
3541 0x03, // Address type (DOMAINNAME).
3542 0x0E, // Length of domain (14)
3543 // Domain string:
3544 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3545 0x00, 0x50, // 16-bit port (80)
3546 };
[email protected]e0c27be2009-07-15 13:09:353547 const char kSOCKS5OkResponse[] =
3548 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3549
3550 MockWrite data_writes[] = {
3551 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3552 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3553 MockWrite("GET / HTTP/1.1\r\n"
3554 "Host: www.google.com\r\n"
3555 "Connection: keep-alive\r\n\r\n")
3556 };
3557
3558 MockRead data_reads[] = {
3559 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3560 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3561 MockRead("HTTP/1.0 200 OK\r\n"),
3562 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3563 MockRead("Payload"),
3564 MockRead(false, OK)
3565 };
3566
[email protected]31a2bfe2010-02-09 08:03:393567 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3568 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593569 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353570
3571 TestCompletionCallback callback;
3572
[email protected]684970b2009-08-14 04:54:463573 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353574 EXPECT_EQ(ERR_IO_PENDING, rv);
3575
3576 rv = callback.WaitForResult();
3577 EXPECT_EQ(OK, rv);
3578
3579 const HttpResponseInfo* response = trans->GetResponseInfo();
3580 EXPECT_FALSE(response == NULL);
3581
3582 std::string response_text;
3583 rv = ReadTransaction(trans.get(), &response_text);
3584 EXPECT_EQ(OK, rv);
3585 EXPECT_EQ("Payload", response_text);
3586}
3587
3588TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093589 SessionDependencies session_deps(
3590 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353591
3592 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433593 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353594
3595 HttpRequestInfo request;
3596 request.method = "GET";
3597 request.url = GURL("https://www.google.com/");
3598 request.load_flags = 0;
3599
3600 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3601 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373602 const unsigned char kSOCKS5OkRequest[] = {
3603 0x05, // Version
3604 0x01, // Command (CONNECT)
3605 0x00, // Reserved.
3606 0x03, // Address type (DOMAINNAME).
3607 0x0E, // Length of domain (14)
3608 // Domain string:
3609 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3610 0x01, 0xBB, // 16-bit port (443)
3611 };
3612
[email protected]e0c27be2009-07-15 13:09:353613 const char kSOCKS5OkResponse[] =
3614 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3615
3616 MockWrite data_writes[] = {
3617 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3618 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3619 arraysize(kSOCKS5OkRequest)),
3620 MockWrite("GET / HTTP/1.1\r\n"
3621 "Host: www.google.com\r\n"
3622 "Connection: keep-alive\r\n\r\n")
3623 };
3624
3625 MockRead data_reads[] = {
3626 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3627 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023628 MockRead("HTTP/1.0 200 OK\r\n"),
3629 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3630 MockRead("Payload"),
3631 MockRead(false, OK)
3632 };
3633
[email protected]31a2bfe2010-02-09 08:03:393634 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3635 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593636 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023637
[email protected]5ecc992a42009-11-11 01:41:593638 SSLSocketDataProvider ssl(true, OK);
3639 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023640
3641 TestCompletionCallback callback;
3642
[email protected]684970b2009-08-14 04:54:463643 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023644 EXPECT_EQ(ERR_IO_PENDING, rv);
3645
3646 rv = callback.WaitForResult();
3647 EXPECT_EQ(OK, rv);
3648
3649 const HttpResponseInfo* response = trans->GetResponseInfo();
3650 EXPECT_FALSE(response == NULL);
3651
3652 std::string response_text;
3653 rv = ReadTransaction(trans.get(), &response_text);
3654 EXPECT_EQ(OK, rv);
3655 EXPECT_EQ("Payload", response_text);
3656}
3657
[email protected]04e5be32009-06-26 20:00:313658// Tests that for connection endpoints the group names are correctly set.
3659TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3660 const struct {
3661 const std::string proxy_server;
3662 const std::string url;
3663 const std::string expected_group_name;
3664 } tests[] = {
3665 {
3666 "", // no proxy (direct)
3667 "http://www.google.com/direct",
3668 "http://www.google.com/",
3669 },
3670 {
3671 "http_proxy",
3672 "http://www.google.com/http_proxy_normal",
3673 "proxy/http_proxy:80/",
3674 },
3675 {
3676 "socks4://socks_proxy:1080",
3677 "http://www.google.com/socks4_direct",
3678 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3679 },
3680
3681 // SSL Tests
3682 {
3683 "",
3684 "https://www.google.com/direct_ssl",
3685 "https://www.google.com/",
3686 },
3687 {
3688 "http_proxy",
3689 "https://www.google.com/http_connect_ssl",
3690 "proxy/http_proxy:80/https://www.google.com/",
3691 },
3692 {
3693 "socks4://socks_proxy:1080",
3694 "https://www.google.com/socks4_ssl",
3695 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3696 },
3697 };
3698
3699 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093700 SessionDependencies session_deps(
3701 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313702
[email protected]04e5be32009-06-26 20:00:313703 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a796bcec2010-03-22 17:17:263704
3705 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
3706 new CaptureGroupNameTCPSocketPool(session.get(),
3707 session->socket_factory()));
3708 session->tcp_socket_pool_ = tcp_conn_pool.get();
3709 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
3710 new CaptureGroupNameSOCKSSocketPool(session.get(),
3711 tcp_conn_pool.get()));
3712 session->socks_socket_pool_ = socks_conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313713
[email protected]5695b8c2009-09-30 21:36:433714 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313715
3716 HttpRequestInfo request;
3717 request.method = "GET";
3718 request.url = GURL(tests[i].url);
3719 request.load_flags = 0;
3720
3721 TestCompletionCallback callback;
3722
3723 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463724 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]a796bcec2010-03-22 17:17:263725 std::string allgroups = tcp_conn_pool->last_group_name_received() +
3726 socks_conn_pool->last_group_name_received();
3727 EXPECT_EQ(tests[i].expected_group_name, allgroups);
[email protected]04e5be32009-06-26 20:00:313728 }
3729}
3730
[email protected]9172a982009-06-06 00:30:253731TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543732 SessionDependencies session_deps(
3733 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323734
[email protected]69719062010-01-05 20:09:213735 // This simulates failure resolving all hostnames; that means we will fail
3736 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:323737 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3738
[email protected]9172a982009-06-06 00:30:253739 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433740 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253741
3742 HttpRequestInfo request;
3743 request.method = "GET";
3744 request.url = GURL("http://www.google.com/");
3745
3746 TestCompletionCallback callback;
3747
[email protected]684970b2009-08-14 04:54:463748 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253749 EXPECT_EQ(ERR_IO_PENDING, rv);
3750
[email protected]9172a982009-06-06 00:30:253751 rv = callback.WaitForResult();
3752 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3753}
3754
[email protected]f3e6c1e2009-06-15 20:52:123755// Host resolution observer used by
3756// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3757// resovle requests are issued with a referrer of |expected_referrer|.
3758class ResolutionReferrerObserver : public HostResolver::Observer {
3759 public:
3760 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3761 : expected_referrer_(expected_referrer),
3762 called_start_with_referrer_(false),
3763 called_finish_with_referrer_(false) {
3764 }
3765
3766 virtual void OnStartResolution(int id,
3767 const HostResolver::RequestInfo& info) {
3768 if (info.referrer() == expected_referrer_)
3769 called_start_with_referrer_ = true;
3770 }
3771
3772 virtual void OnFinishResolutionWithStatus(
3773 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3774 if (info.referrer() == expected_referrer_)
3775 called_finish_with_referrer_ = true;
3776 }
3777
[email protected]eb255d32009-06-17 02:11:033778 virtual void OnCancelResolution(int id,
3779 const HostResolver::RequestInfo& info ) {
3780 FAIL() << "Should not be cancelling any requests!";
3781 }
3782
[email protected]f3e6c1e2009-06-15 20:52:123783 bool did_complete_with_expected_referrer() const {
3784 return called_start_with_referrer_ && called_finish_with_referrer_;
3785 }
3786
3787 private:
3788 GURL expected_referrer_;
3789 bool called_start_with_referrer_;
3790 bool called_finish_with_referrer_;
3791
3792 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3793};
3794
3795// Make sure that when HostResolver::Resolve() is invoked, it passes through
3796// the "referrer". This is depended on by the DNS prefetch observer.
3797TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3798 GURL referrer = GURL("http://expected-referrer/");
3799 EXPECT_TRUE(referrer.is_valid());
3800 ResolutionReferrerObserver resolution_observer(referrer);
3801
3802 SessionDependencies session_deps;
3803 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433804 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123805
3806 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143807 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123808
3809 // Connect up a mock socket which will fail when reading.
3810 MockRead data_reads[] = {
3811 MockRead(false, ERR_FAILED),
3812 };
[email protected]31a2bfe2010-02-09 08:03:393813 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593814 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:123815
3816 // Issue a request, containing an HTTP referrer.
3817 HttpRequestInfo request;
3818 request.method = "GET";
3819 request.referrer = referrer;
3820 request.url = GURL("http://www.google.com/");
3821
3822 // Run the request until it fails reading from the socket.
3823 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463824 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123825 EXPECT_EQ(ERR_IO_PENDING, rv);
3826 rv = callback.WaitForResult();
3827 EXPECT_EQ(ERR_FAILED, rv);
3828
3829 // Check that the host resolution observer saw |referrer|.
3830 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3831}
3832
[email protected]3b9cca42009-06-16 01:08:283833// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3834// host cache is bypassed.
3835TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3836 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323837
[email protected]a2c2fb92009-07-18 07:31:043838 // Select a host resolver that does caching.
3839 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323840
[email protected]3b9cca42009-06-16 01:08:283841 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433842 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:283843
3844 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3845 // a synchronous lookup.)
3846 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143847 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463848 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3849 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283850 EXPECT_EQ(OK, rv);
3851
3852 // Verify that it was added to host cache, by doing a subsequent async lookup
3853 // and confirming it completes synchronously.
3854 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463855 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283856 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463857 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323858 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283859
3860 // Inject a failure the next time that "www.google.com" is resolved. This way
3861 // we can tell if the next lookup hit the cache, or the "network".
3862 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323863 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283864
3865 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3866 // first read -- this won't be reached as the host resolution will fail first.
3867 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:393868 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593869 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:283870
3871 // Issue a request, asking to bypass the cache(s).
3872 HttpRequestInfo request;
3873 request.method = "GET";
3874 request.load_flags = LOAD_BYPASS_CACHE;
3875 request.url = GURL("http://www.google.com/");
3876
3877 // Run the request.
3878 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463879 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283880 ASSERT_EQ(ERR_IO_PENDING, rv);
3881 rv = callback.WaitForResult();
3882
3883 // If we bypassed the cache, we would have gotten a failure while resolving
3884 // "www.google.com".
3885 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3886}
3887
[email protected]0877e3d2009-10-17 22:29:573888// Make sure we can handle an error when writing the request.
3889TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3890 SessionDependencies session_deps;
3891 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3892
3893 HttpRequestInfo request;
3894 request.method = "GET";
3895 request.url = GURL("http://www.foo.com/");
3896 request.load_flags = 0;
3897
3898 MockWrite write_failure[] = {
3899 MockWrite(true, ERR_CONNECTION_RESET),
3900 };
[email protected]31a2bfe2010-02-09 08:03:393901 StaticSocketDataProvider data(NULL, 0,
3902 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:593903 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573904
3905 TestCompletionCallback callback;
3906
3907 scoped_ptr<HttpTransaction> trans(
3908 new HttpNetworkTransaction(CreateSession(&session_deps)));
3909
3910 int rv = trans->Start(&request, &callback, NULL);
3911 EXPECT_EQ(ERR_IO_PENDING, rv);
3912
3913 rv = callback.WaitForResult();
3914 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3915}
3916
3917// Check that a connection closed after the start of the headers finishes ok.
3918TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3919 SessionDependencies session_deps;
3920 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3921
3922 HttpRequestInfo request;
3923 request.method = "GET";
3924 request.url = GURL("http://www.foo.com/");
3925 request.load_flags = 0;
3926
3927 MockRead data_reads[] = {
3928 MockRead("HTTP/1."),
3929 MockRead(false, OK),
3930 };
3931
[email protected]31a2bfe2010-02-09 08:03:393932 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593933 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573934
3935 TestCompletionCallback callback;
3936
3937 scoped_ptr<HttpTransaction> trans(
3938 new HttpNetworkTransaction(CreateSession(&session_deps)));
3939
3940 int rv = trans->Start(&request, &callback, NULL);
3941 EXPECT_EQ(ERR_IO_PENDING, rv);
3942
3943 rv = callback.WaitForResult();
3944 EXPECT_EQ(OK, rv);
3945
3946 const HttpResponseInfo* response = trans->GetResponseInfo();
3947 EXPECT_TRUE(response != NULL);
3948
3949 EXPECT_TRUE(response->headers != NULL);
3950 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
3951
3952 std::string response_data;
3953 rv = ReadTransaction(trans.get(), &response_data);
3954 EXPECT_EQ(OK, rv);
3955 EXPECT_EQ("", response_data);
3956}
3957
3958// Make sure that a dropped connection while draining the body for auth
3959// restart does the right thing.
3960TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
3961 SessionDependencies session_deps;
3962 scoped_ptr<HttpTransaction> trans(
3963 new HttpNetworkTransaction(CreateSession(&session_deps)));
3964
3965 HttpRequestInfo request;
3966 request.method = "GET";
3967 request.url = GURL("http://www.google.com/");
3968 request.load_flags = 0;
3969
3970 MockWrite data_writes1[] = {
3971 MockWrite("GET / HTTP/1.1\r\n"
3972 "Host: www.google.com\r\n"
3973 "Connection: keep-alive\r\n\r\n"),
3974 };
3975
3976 MockRead data_reads1[] = {
3977 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3978 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3979 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3980 MockRead("Content-Length: 14\r\n\r\n"),
3981 MockRead("Unauth"),
3982 MockRead(true, ERR_CONNECTION_RESET),
3983 };
3984
[email protected]31a2bfe2010-02-09 08:03:393985 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3986 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593987 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:573988
3989 // After calling trans->RestartWithAuth(), this is the request we should
3990 // be issuing -- the final header line contains the credentials.
3991 MockWrite data_writes2[] = {
3992 MockWrite("GET / HTTP/1.1\r\n"
3993 "Host: www.google.com\r\n"
3994 "Connection: keep-alive\r\n"
3995 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3996 };
3997
3998 // Lastly, the server responds with the actual content.
3999 MockRead data_reads2[] = {
4000 MockRead("HTTP/1.1 200 OK\r\n"),
4001 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4002 MockRead("Content-Length: 100\r\n\r\n"),
4003 MockRead(false, OK),
4004 };
4005
[email protected]31a2bfe2010-02-09 08:03:394006 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4007 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594008 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574009
4010 TestCompletionCallback callback1;
4011
4012 int rv = trans->Start(&request, &callback1, NULL);
4013 EXPECT_EQ(ERR_IO_PENDING, rv);
4014
4015 rv = callback1.WaitForResult();
4016 EXPECT_EQ(OK, rv);
4017
4018 const HttpResponseInfo* response = trans->GetResponseInfo();
4019 EXPECT_FALSE(response == NULL);
4020
4021 // The password prompt info should have been set in response->auth_challenge.
4022 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4023
4024 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4025 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4026 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4027
4028 TestCompletionCallback callback2;
4029
4030 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4031 EXPECT_EQ(ERR_IO_PENDING, rv);
4032
4033 rv = callback2.WaitForResult();
4034 EXPECT_EQ(OK, rv);
4035
4036 response = trans->GetResponseInfo();
4037 EXPECT_FALSE(response == NULL);
4038 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4039 EXPECT_EQ(100, response->headers->GetContentLength());
4040}
4041
4042// Test HTTPS connections going through a proxy that sends extra data.
4043TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4044 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4045
4046 HttpRequestInfo request;
4047 request.method = "GET";
4048 request.url = GURL("https://www.google.com/");
4049 request.load_flags = 0;
4050
4051 MockRead proxy_reads[] = {
4052 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4053 MockRead(false, OK)
4054 };
4055
[email protected]31a2bfe2010-02-09 08:03:394056 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594057 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574058
[email protected]5ecc992a42009-11-11 01:41:594059 session_deps.socket_factory.AddSocketDataProvider(&data);
4060 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574061
4062 TestCompletionCallback callback;
4063
4064 session_deps.socket_factory.ResetNextMockIndexes();
4065
4066 scoped_ptr<HttpTransaction> trans(
4067 new HttpNetworkTransaction(CreateSession(&session_deps)));
4068
4069 int rv = trans->Start(&request, &callback, NULL);
4070 EXPECT_EQ(ERR_IO_PENDING, rv);
4071
4072 rv = callback.WaitForResult();
4073 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4074}
4075
[email protected]e22e1362009-11-23 21:31:124076TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464077 SessionDependencies session_deps;
4078 scoped_ptr<HttpTransaction> trans(
4079 new HttpNetworkTransaction(CreateSession(&session_deps)));
4080
4081 HttpRequestInfo request;
4082 request.method = "GET";
4083 request.url = GURL("http://www.google.com/");
4084 request.load_flags = 0;
4085
[email protected]e22e1362009-11-23 21:31:124086 MockRead data_reads[] = {
4087 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4088 MockRead(false, OK),
4089 };
[email protected]9492e4a2010-02-24 00:58:464090
4091 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4092 session_deps.socket_factory.AddSocketDataProvider(&data);
4093
4094 TestCompletionCallback callback;
4095
4096 int rv = trans->Start(&request, &callback, NULL);
4097 EXPECT_EQ(ERR_IO_PENDING, rv);
4098
4099 EXPECT_EQ(OK, callback.WaitForResult());
4100
4101 const HttpResponseInfo* response = trans->GetResponseInfo();
4102 EXPECT_TRUE(response != NULL);
4103
4104 EXPECT_TRUE(response->headers != NULL);
4105 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4106
4107 std::string response_data;
4108 rv = ReadTransaction(trans.get(), &response_data);
4109 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124110}
4111
[email protected]95d88ffe2010-02-04 21:25:334112TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4113 SessionDependencies session_deps;
4114 scoped_ptr<HttpTransaction> trans(
4115 new HttpNetworkTransaction(CreateSession(&session_deps)));
4116
4117 HttpRequestInfo request;
4118 request.method = "POST";
4119 request.url = GURL("http://www.google.com/upload");
4120 request.upload_data = new UploadData;
4121 request.load_flags = 0;
4122
4123 FilePath temp_file_path;
4124 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4125 const uint64 kFakeSize = 100000; // file is actually blank
4126
4127 std::vector<UploadData::Element> elements;
4128 UploadData::Element element;
4129 element.SetToFilePath(temp_file_path);
4130 element.SetContentLength(kFakeSize);
4131 elements.push_back(element);
4132 request.upload_data->set_elements(elements);
4133 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4134
4135 MockRead data_reads[] = {
4136 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4137 MockRead("hello world"),
4138 MockRead(false, OK),
4139 };
[email protected]31a2bfe2010-02-09 08:03:394140 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334141 session_deps.socket_factory.AddSocketDataProvider(&data);
4142
4143 TestCompletionCallback callback;
4144
4145 int rv = trans->Start(&request, &callback, NULL);
4146 EXPECT_EQ(ERR_IO_PENDING, rv);
4147
4148 rv = callback.WaitForResult();
4149 EXPECT_EQ(OK, rv);
4150
4151 const HttpResponseInfo* response = trans->GetResponseInfo();
4152 EXPECT_TRUE(response != NULL);
4153
4154 EXPECT_TRUE(response->headers != NULL);
4155 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4156
4157 std::string response_data;
4158 rv = ReadTransaction(trans.get(), &response_data);
4159 EXPECT_EQ(OK, rv);
4160 EXPECT_EQ("hello world", response_data);
4161
4162 file_util::Delete(temp_file_path, false);
4163}
4164
[email protected]6624b4622010-03-29 19:58:364165TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4166 // If we try to upload an unreadable file, the network stack should report
4167 // the file size as zero and upload zero bytes for that file.
4168 SessionDependencies session_deps;
4169 scoped_ptr<HttpTransaction> trans(
4170 new HttpNetworkTransaction(CreateSession(&session_deps)));
4171
4172 FilePath temp_file;
4173 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4174 std::string temp_file_content("Unreadable file.");
4175 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4176 temp_file_content.length()));
4177 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4178
4179 HttpRequestInfo request;
4180 request.method = "POST";
4181 request.url = GURL("http://www.google.com/upload");
4182 request.upload_data = new UploadData;
4183 request.load_flags = 0;
4184
4185 std::vector<UploadData::Element> elements;
4186 UploadData::Element element;
4187 element.SetToFilePath(temp_file);
4188 elements.push_back(element);
4189 request.upload_data->set_elements(elements);
4190
4191 MockRead data_reads[] = {
4192 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4193 MockRead(false, OK),
4194 };
4195 MockWrite data_writes[] = {
4196 MockWrite("POST /upload HTTP/1.1\r\n"
4197 "Host: www.google.com\r\n"
4198 "Connection: keep-alive\r\n"
4199 "Content-Length: 0\r\n\r\n"),
4200 MockWrite(false, OK),
4201 };
4202 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4203 arraysize(data_writes));
4204 session_deps.socket_factory.AddSocketDataProvider(&data);
4205
4206 TestCompletionCallback callback;
4207
4208 int rv = trans->Start(&request, &callback, NULL);
4209 EXPECT_EQ(ERR_IO_PENDING, rv);
4210
4211 rv = callback.WaitForResult();
4212 EXPECT_EQ(OK, rv);
4213
4214 const HttpResponseInfo* response = trans->GetResponseInfo();
4215 EXPECT_TRUE(response != NULL);
4216 EXPECT_TRUE(response->headers != NULL);
4217 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4218
4219 file_util::Delete(temp_file, false);
4220}
4221
4222TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4223 SessionDependencies session_deps;
4224 scoped_ptr<HttpTransaction> trans(
4225 new HttpNetworkTransaction(CreateSession(&session_deps)));
4226
4227 FilePath temp_file;
4228 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4229 std::string temp_file_contents("Unreadable file.");
4230 std::string unreadable_contents(temp_file_contents.length(), '\0');
4231 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4232 temp_file_contents.length()));
4233
4234 HttpRequestInfo request;
4235 request.method = "POST";
4236 request.url = GURL("http://www.google.com/upload");
4237 request.upload_data = new UploadData;
4238 request.load_flags = 0;
4239
4240 std::vector<UploadData::Element> elements;
4241 UploadData::Element element;
4242 element.SetToFilePath(temp_file);
4243 elements.push_back(element);
4244 request.upload_data->set_elements(elements);
4245
4246 MockRead data_reads[] = {
4247 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4248 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4249 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4250
4251 MockRead("HTTP/1.1 200 OK\r\n"),
4252 MockRead("Content-Length: 0\r\n\r\n"),
4253 MockRead(false, OK),
4254 };
4255 MockWrite data_writes[] = {
4256 MockWrite("POST /upload HTTP/1.1\r\n"
4257 "Host: www.google.com\r\n"
4258 "Connection: keep-alive\r\n"
4259 "Content-Length: 16\r\n\r\n"),
4260 MockWrite(false, temp_file_contents.c_str()),
4261
4262 MockWrite("POST /upload HTTP/1.1\r\n"
4263 "Host: www.google.com\r\n"
4264 "Connection: keep-alive\r\n"
4265 "Content-Length: 16\r\n"
4266 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4267 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4268 MockWrite(false, OK),
4269 };
4270 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4271 arraysize(data_writes));
4272 session_deps.socket_factory.AddSocketDataProvider(&data);
4273
4274 TestCompletionCallback callback1;
4275
4276 int rv = trans->Start(&request, &callback1, NULL);
4277 EXPECT_EQ(ERR_IO_PENDING, rv);
4278
4279 rv = callback1.WaitForResult();
4280 EXPECT_EQ(OK, rv);
4281
4282 const HttpResponseInfo* response = trans->GetResponseInfo();
4283 EXPECT_TRUE(response != NULL);
4284 EXPECT_TRUE(response->headers != NULL);
4285 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4286
4287 // The password prompt info should have been set in response->auth_challenge.
4288 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4289 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4290 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4291 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4292
4293 // Now make the file unreadable and try again.
4294 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4295
4296 TestCompletionCallback callback2;
4297
4298 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4299 EXPECT_EQ(ERR_IO_PENDING, rv);
4300
4301 rv = callback2.WaitForResult();
4302 EXPECT_EQ(OK, rv);
4303
4304 response = trans->GetResponseInfo();
4305 EXPECT_TRUE(response != NULL);
4306 EXPECT_TRUE(response->headers != NULL);
4307 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4308 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4309
4310 file_util::Delete(temp_file, false);
4311}
4312
[email protected]aeefc9e82010-02-19 16:18:274313// Tests that changes to Auth realms are treated like auth rejections.
4314TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4315 SessionDependencies session_deps;
4316 scoped_ptr<HttpTransaction> trans(
4317 new HttpNetworkTransaction(CreateSession(&session_deps)));
4318
4319 HttpRequestInfo request;
4320 request.method = "GET";
4321 request.url = GURL("http://www.google.com/");
4322 request.load_flags = 0;
4323
4324 // First transaction will request a resource and receive a Basic challenge
4325 // with realm="first_realm".
4326 MockWrite data_writes1[] = {
4327 MockWrite("GET / HTTP/1.1\r\n"
4328 "Host: www.google.com\r\n"
4329 "Connection: keep-alive\r\n"
4330 "\r\n"),
4331 };
4332 MockRead data_reads1[] = {
4333 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4334 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4335 "\r\n"),
4336 };
4337
4338 // After calling trans->RestartWithAuth(), provide an Authentication header
4339 // for first_realm. The server will reject and provide a challenge with
4340 // second_realm.
4341 MockWrite data_writes2[] = {
4342 MockWrite("GET / HTTP/1.1\r\n"
4343 "Host: www.google.com\r\n"
4344 "Connection: keep-alive\r\n"
4345 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4346 "\r\n"),
4347 };
4348 MockRead data_reads2[] = {
4349 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4350 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4351 "\r\n"),
4352 };
4353
4354 // This again fails, and goes back to first_realm. Make sure that the
4355 // entry is removed from cache.
4356 MockWrite data_writes3[] = {
4357 MockWrite("GET / HTTP/1.1\r\n"
4358 "Host: www.google.com\r\n"
4359 "Connection: keep-alive\r\n"
4360 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4361 "\r\n"),
4362 };
4363 MockRead data_reads3[] = {
4364 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4365 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4366 "\r\n"),
4367 };
4368
4369 // Try one last time (with the correct password) and get the resource.
4370 MockWrite data_writes4[] = {
4371 MockWrite("GET / HTTP/1.1\r\n"
4372 "Host: www.google.com\r\n"
4373 "Connection: keep-alive\r\n"
4374 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4375 "\r\n"),
4376 };
4377 MockRead data_reads4[] = {
4378 MockRead("HTTP/1.1 200 OK\r\n"
4379 "Content-Type: text/html; charset=iso-8859-1\r\n"
4380 "Content-Length: 100\r\n"
4381 "\r\n"),
4382 };
4383
4384 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4385 data_writes1, arraysize(data_writes1));
4386 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4387 data_writes2, arraysize(data_writes2));
4388 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4389 data_writes3, arraysize(data_writes3));
4390 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4391 data_writes4, arraysize(data_writes4));
4392 session_deps.socket_factory.AddSocketDataProvider(&data1);
4393 session_deps.socket_factory.AddSocketDataProvider(&data2);
4394 session_deps.socket_factory.AddSocketDataProvider(&data3);
4395 session_deps.socket_factory.AddSocketDataProvider(&data4);
4396
4397 TestCompletionCallback callback1;
4398
4399 // Issue the first request with Authorize headers. There should be a
4400 // password prompt for first_realm waiting to be filled in after the
4401 // transaction completes.
4402 int rv = trans->Start(&request, &callback1, NULL);
4403 EXPECT_EQ(ERR_IO_PENDING, rv);
4404 rv = callback1.WaitForResult();
4405 EXPECT_EQ(OK, rv);
4406 const HttpResponseInfo* response = trans->GetResponseInfo();
4407 ASSERT_FALSE(response == NULL);
4408 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4409 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4410 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4411 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4412
4413 // Issue the second request with an incorrect password. There should be a
4414 // password prompt for second_realm waiting to be filled in after the
4415 // transaction completes.
4416 TestCompletionCallback callback2;
4417 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4418 EXPECT_EQ(ERR_IO_PENDING, rv);
4419 rv = callback2.WaitForResult();
4420 EXPECT_EQ(OK, rv);
4421 response = trans->GetResponseInfo();
4422 ASSERT_FALSE(response == NULL);
4423 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4424 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4425 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4426 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4427
4428 // Issue the third request with another incorrect password. There should be
4429 // a password prompt for first_realm waiting to be filled in. If the password
4430 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4431 // first_realm was not correctly removed.
4432 TestCompletionCallback callback3;
4433 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4434 EXPECT_EQ(ERR_IO_PENDING, rv);
4435 rv = callback3.WaitForResult();
4436 EXPECT_EQ(OK, rv);
4437 response = trans->GetResponseInfo();
4438 ASSERT_FALSE(response == NULL);
4439 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4440 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4441 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4442 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4443
4444 // Issue the fourth request with the correct password and username.
4445 TestCompletionCallback callback4;
4446 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4447 EXPECT_EQ(ERR_IO_PENDING, rv);
4448 rv = callback4.WaitForResult();
4449 EXPECT_EQ(OK, rv);
4450 response = trans->GetResponseInfo();
4451 ASSERT_FALSE(response == NULL);
4452 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4453}
4454
[email protected]564b4912010-03-09 16:30:424455TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424456 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
4457
[email protected]564b4912010-03-09 16:30:424458 SessionDependencies session_deps;
4459
4460 MockRead data_reads[] = {
4461 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]a2cb8122010-03-10 17:22:424462 MockRead("Alternate-Protocol: 443:npn-spdy\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424463 MockRead("hello world"),
4464 MockRead(false, OK),
4465 };
4466
4467 HttpRequestInfo request;
4468 request.method = "GET";
4469 request.url = GURL("http://www.google.com/");
4470 request.load_flags = 0;
4471
4472 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4473
4474 session_deps.socket_factory.AddSocketDataProvider(&data);
4475
4476 TestCompletionCallback callback;
4477
4478 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4479 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4480
4481 int rv = trans->Start(&request, &callback, NULL);
4482 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534483
[email protected]564b4912010-03-09 16:30:424484 HostPortPair http_host_port_pair;
4485 http_host_port_pair.host = "www.google.com";
4486 http_host_port_pair.port = 80;
4487 const HttpAlternateProtocols& alternate_protocols =
4488 session->alternate_protocols();
4489 EXPECT_FALSE(
4490 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4491
4492 EXPECT_EQ(OK, callback.WaitForResult());
4493
4494 const HttpResponseInfo* response = trans->GetResponseInfo();
4495 ASSERT_TRUE(response != NULL);
4496 ASSERT_TRUE(response->headers != NULL);
4497 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4498
4499 std::string response_data;
4500 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4501 EXPECT_EQ("hello world", response_data);
4502
4503 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4504 const HttpAlternateProtocols::PortProtocolPair alternate =
4505 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4506 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4507 expected_alternate.port = 443;
[email protected]a2cb8122010-03-10 17:22:424508 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY;
[email protected]564b4912010-03-09 16:30:424509 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424510
4511 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424512}
4513
4514TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
4515 SessionDependencies session_deps;
4516
4517 HttpRequestInfo request;
4518 request.method = "GET";
4519 request.url = GURL("http://www.google.com/");
4520 request.load_flags = 0;
4521
4522 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4523 StaticSocketDataProvider first_data;
4524 first_data.set_connect_data(mock_connect);
4525 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4526
4527 MockRead data_reads[] = {
4528 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4529 MockRead("hello world"),
4530 MockRead(true, OK),
4531 };
4532 StaticSocketDataProvider second_data(
4533 data_reads, arraysize(data_reads), NULL, 0);
4534 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4535
4536 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4537 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4538 // http://crbug.com/37454.
4539 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4540
4541 TestCompletionCallback callback;
4542
4543 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4544
4545 HostPortPair http_host_port_pair;
4546 http_host_port_pair.host = "www.google.com";
4547 http_host_port_pair.port = 80;
4548 HttpAlternateProtocols* alternate_protocols =
4549 session->mutable_alternate_protocols();
4550 alternate_protocols->SetAlternateProtocolFor(
4551 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]a2cb8122010-03-10 17:22:424552 HttpAlternateProtocols::NPN_SPDY);
[email protected]564b4912010-03-09 16:30:424553
4554 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4555
4556 int rv = trans->Start(&request, &callback, NULL);
4557 EXPECT_EQ(ERR_IO_PENDING, rv);
4558 EXPECT_EQ(OK, callback.WaitForResult());
4559
4560 const HttpResponseInfo* response = trans->GetResponseInfo();
4561 ASSERT_TRUE(response != NULL);
4562 ASSERT_TRUE(response->headers != NULL);
4563 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4564
4565 std::string response_data;
4566 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4567 EXPECT_EQ("hello world", response_data);
4568
4569 ASSERT_TRUE(
4570 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
4571 const HttpAlternateProtocols::PortProtocolPair alternate =
4572 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
4573 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
4574}
4575
4576// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
4577// says that it does SPDY, but it just does the TLS handshake, but the NPN
4578// response does not indicate SPDY, so we just do standard HTTPS over the port.
4579// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
4580// on the original port.
[email protected]a2cb8122010-03-10 17:22:424581// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
4582// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:534583//
[email protected]a2cb8122010-03-10 17:22:424584// HttpRequestInfo request;
4585// request.method = "GET";
4586// request.url = GURL("http://www.google.com/");
4587// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:534588//
[email protected]a2cb8122010-03-10 17:22:424589// MockRead data_reads[] = {
4590// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4591// MockRead("hello world"),
4592// MockRead(true, OK),
4593// };
4594// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4595// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:534596//
[email protected]a2cb8122010-03-10 17:22:424597// SSLSocketDataProvider ssl(true, OK);
4598// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:534599//
[email protected]a2cb8122010-03-10 17:22:424600// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:534601//
[email protected]a2cb8122010-03-10 17:22:424602// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:534603//
[email protected]a2cb8122010-03-10 17:22:424604// HostPortPair http_host_port_pair;
4605// http_host_port_pair.host = "www.google.com";
4606// http_host_port_pair.port = 80;
4607// HttpAlternateProtocols* alternate_protocols =
4608// session->mutable_alternate_protocols();
4609// alternate_protocols->SetAlternateProtocolFor(
4610// http_host_port_pair, 1234 /* port is ignored */,
4611// HttpAlternateProtocols::NPN_SPDY);
[email protected]9e743cd2010-03-16 07:03:534612//
[email protected]a2cb8122010-03-10 17:22:424613// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:534614//
[email protected]a2cb8122010-03-10 17:22:424615// int rv = trans->Start(&request, &callback, NULL);
4616// EXPECT_EQ(ERR_IO_PENDING, rv);
4617// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:534618//
[email protected]a2cb8122010-03-10 17:22:424619// const HttpResponseInfo* response = trans->GetResponseInfo();
4620// ASSERT_TRUE(response != NULL);
4621// ASSERT_TRUE(response->headers != NULL);
4622// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:534623//
[email protected]a2cb8122010-03-10 17:22:424624// std::string response_data;
4625// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4626// EXPECT_EQ("hello world", response_data);
4627// }
4628
4629TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]564b4912010-03-09 16:30:424630 SessionDependencies session_deps;
4631
4632 HttpRequestInfo request;
4633 request.method = "GET";
4634 request.url = GURL("http://www.google.com/");
4635 request.load_flags = 0;
4636
[email protected]a2cb8122010-03-10 17:22:424637 StaticSocketDataProvider first_tcp_connect;
4638 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
4639
4640 SSLSocketDataProvider ssl(true, OK);
4641 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4642
[email protected]564b4912010-03-09 16:30:424643 MockRead data_reads[] = {
4644 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4645 MockRead("hello world"),
4646 MockRead(true, OK),
4647 };
[email protected]a2cb8122010-03-10 17:22:424648 StaticSocketDataProvider fallback_data(
4649 data_reads, arraysize(data_reads), NULL, 0);
4650 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:424651
4652 TestCompletionCallback callback;
4653
4654 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4655
4656 HostPortPair http_host_port_pair;
4657 http_host_port_pair.host = "www.google.com";
4658 http_host_port_pair.port = 80;
4659 HttpAlternateProtocols* alternate_protocols =
4660 session->mutable_alternate_protocols();
4661 alternate_protocols->SetAlternateProtocolFor(
4662 http_host_port_pair, 1234 /* port is ignored */,
[email protected]a2cb8122010-03-10 17:22:424663 HttpAlternateProtocols::NPN_SPDY);
[email protected]564b4912010-03-09 16:30:424664
4665 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4666
4667 int rv = trans->Start(&request, &callback, NULL);
4668 EXPECT_EQ(ERR_IO_PENDING, rv);
4669 EXPECT_EQ(OK, callback.WaitForResult());
4670
4671 const HttpResponseInfo* response = trans->GetResponseInfo();
4672 ASSERT_TRUE(response != NULL);
4673 ASSERT_TRUE(response->headers != NULL);
4674 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4675
4676 std::string response_data;
4677 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4678 EXPECT_EQ("hello world", response_data);
4679}
4680
[email protected]e5ae96a2010-04-14 20:12:454681// MockAuthHandlerCanonical is used by the ResolveCanonicalName
4682// HttpNetworkTransaction unit test below. Callers set up expectations for
4683// whether the canonical name needs to be resolved.
4684class MockAuthHandlerCanonical : public HttpAuthHandler {
4685 public:
4686 enum Resolve {
4687 RESOLVE_INIT,
4688 RESOLVE_SKIP,
4689 RESOLVE_SYNC,
4690 RESOLVE_ASYNC,
4691 RESOLVE_TESTED,
4692 };
4693
4694 MockAuthHandlerCanonical() : resolve_(RESOLVE_INIT), user_callback_(NULL) {}
4695 virtual ~MockAuthHandlerCanonical() {}
4696
4697 void SetResolveExpectation(Resolve resolve) {
4698 EXPECT_EQ(RESOLVE_INIT, resolve_);
4699 resolve_ = resolve;
4700 }
4701
4702 void ResetResolveExpectation() {
4703 EXPECT_EQ(RESOLVE_TESTED, resolve_);
4704 resolve_ = RESOLVE_INIT;
4705 }
4706
4707 virtual bool NeedsCanonicalName() {
4708 switch (resolve_) {
4709 case RESOLVE_SYNC:
4710 case RESOLVE_ASYNC:
4711 return true;
4712 case RESOLVE_SKIP:
4713 resolve_ = RESOLVE_TESTED;
4714 return false;
4715 default:
4716 NOTREACHED();
4717 return false;
4718 }
4719 }
4720
4721 virtual int ResolveCanonicalName(HostResolver* host_resolver,
4722 CompletionCallback* callback,
4723 const BoundNetLog& net_log) {
4724 EXPECT_NE(RESOLVE_TESTED, resolve_);
4725 int rv = OK;
4726 switch (resolve_) {
4727 case RESOLVE_SYNC:
4728 resolve_ = RESOLVE_TESTED;
4729 break;
4730 case RESOLVE_ASYNC:
4731 EXPECT_TRUE(user_callback_ == NULL);
4732 rv = ERR_IO_PENDING;
4733 user_callback_ = callback;
4734 MessageLoop::current()->PostTask(
4735 FROM_HERE,
4736 NewRunnableMethod(
4737 this, &MockAuthHandlerCanonical::OnResolveCanonicalName));
4738 break;
4739 default:
4740 NOTREACHED();
4741 break;
4742 }
4743 return rv;
4744 }
4745
4746 void OnResolveCanonicalName() {
4747 EXPECT_EQ(RESOLVE_ASYNC, resolve_);
4748 EXPECT_TRUE(user_callback_ != NULL);
4749 resolve_ = RESOLVE_TESTED;
4750 CompletionCallback* callback = user_callback_;
4751 user_callback_ = NULL;
4752 callback->Run(OK);
4753 }
4754
4755 virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) {
4756 scheme_ = "mock";
4757 score_ = 1;
4758 properties_ = 0;
4759 return true;
4760 }
4761
4762 virtual int GenerateAuthToken(const std::wstring& username,
4763 const std::wstring& password,
4764 const HttpRequestInfo* request,
4765 const ProxyInfo* proxy,
4766 std::string* auth_token) {
4767 auth_token->assign("Mock AUTH myserver.example.com");
4768 return OK;
4769 }
4770
4771 virtual int GenerateDefaultAuthToken(const HttpRequestInfo* request,
4772 const ProxyInfo* proxy,
4773 std::string* auth_token) {
4774 auth_token->assign("Mock DEFAULT_AUTH myserver.example.com");
4775 return OK;
4776 }
4777
4778 // The Factory class simply returns the same handler each time
4779 // CreateAuthHandler is called.
4780 class Factory : public HttpAuthHandlerFactory {
4781 public:
4782 Factory() {}
4783 virtual ~Factory() {}
4784
4785 void set_mock_handler(MockAuthHandlerCanonical* mock_handler) {
4786 mock_handler_ = mock_handler;
4787 }
4788 MockAuthHandlerCanonical* mock_handler() const {
4789 return mock_handler_.get();
4790 }
4791
4792 virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
4793 HttpAuth::Target target,
4794 const GURL& origin,
4795 scoped_refptr<HttpAuthHandler>* handler) {
4796 *handler = mock_handler_;
4797 return OK;
4798 }
4799
4800 private:
4801 scoped_refptr<MockAuthHandlerCanonical> mock_handler_;
4802 };
4803
4804 private:
4805 Resolve resolve_;
4806 CompletionCallback* user_callback_;
4807};
4808
4809// Tests that ResolveCanonicalName is handled correctly by the
4810// HttpNetworkTransaction.
4811TEST_F(HttpNetworkTransactionTest, ResolveCanonicalName) {
4812 SessionDependencies session_deps;
4813 scoped_refptr<MockAuthHandlerCanonical> auth_handler(
4814 new MockAuthHandlerCanonical());
4815 auth_handler->Init(NULL);
4816 MockAuthHandlerCanonical::Factory* auth_factory(
4817 new MockAuthHandlerCanonical::Factory());
4818 auth_factory->set_mock_handler(auth_handler);
4819 session_deps.http_auth_handler_factory.reset(auth_factory);
4820
4821 for (int i = 0; i < 2; ++i) {
4822 scoped_ptr<HttpTransaction> trans(
4823 new HttpNetworkTransaction(CreateSession(&session_deps)));
4824
4825 // Set up expectations for this pass of the test. Many of the EXPECT calls
4826 // are contained inside the MockAuthHandlerCanonical codebase in response to
4827 // the expectations.
4828 MockAuthHandlerCanonical::Resolve resolve = (i == 0) ?
4829 MockAuthHandlerCanonical::RESOLVE_SYNC :
4830 MockAuthHandlerCanonical::RESOLVE_ASYNC;
4831 auth_handler->SetResolveExpectation(resolve);
4832 HttpRequestInfo request;
4833 request.method = "GET";
4834 request.url = GURL("http://myserver/");
4835 request.load_flags = 0;
4836
4837 MockWrite data_writes1[] = {
4838 MockWrite("GET / HTTP/1.1\r\n"
4839 "Host: myserver\r\n"
4840 "Connection: keep-alive\r\n\r\n"),
4841 };
4842
4843 MockRead data_reads1[] = {
4844 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4845 MockRead("WWW-Authenticate: Mock myserver.example.com\r\n"),
4846 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4847 MockRead("Content-Length: 14\r\n\r\n"),
4848 MockRead("Unauthorized\r\n"),
4849 };
4850
4851 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4852 data_writes1, arraysize(data_writes1));
4853 session_deps.socket_factory.AddSocketDataProvider(&data1);
4854
4855 TestCompletionCallback callback1;
4856
4857 int rv = trans->Start(&request, &callback1, NULL);
4858 EXPECT_EQ(ERR_IO_PENDING, rv);
4859
4860 rv = callback1.WaitForResult();
4861 EXPECT_EQ(OK, rv);
4862
4863 const HttpResponseInfo* response = trans->GetResponseInfo();
4864 EXPECT_FALSE(response == NULL);
4865
4866 // The password prompt is set after the canonical name is resolved.
4867 // If it isn't present or is incorrect, it indicates that the scheme
4868 // did not complete correctly.
4869 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4870
4871 EXPECT_EQ(L"myserver:80", response->auth_challenge->host_and_port);
4872 EXPECT_EQ(L"", response->auth_challenge->realm);
4873 EXPECT_EQ(L"mock", response->auth_challenge->scheme);
4874 auth_handler->ResetResolveExpectation();
4875 }
4876}
4877
[email protected]89ceba9a2009-03-21 03:46:064878} // namespace net