blob: f3991ce861dd974157f466929c188ec6adf3b7e0 [file] [log] [blame]
[email protected]95d88ffe2010-02-04 21:25:331// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]77848d12008-11-14 00:00:225#include <math.h> // ceil
[email protected]95d88ffe2010-02-04 21:25:336#include <vector>
[email protected]77848d12008-11-14 00:00:227
[email protected]68bf9152008-09-25 19:47:308#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:339#include "base/file_path.h"
10#include "base/file_util.h"
[email protected]bacff652009-03-31 17:50:3311#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3212#include "net/base/mock_host_resolver.h"
[email protected]ac790b42009-12-02 04:31:3113#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4214#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3315#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5216#include "net/base/test_completion_callback.h"
17#include "net/base/upload_data.h"
[email protected]dab9c7d2010-02-06 21:44:3218#include "net/spdy/spdy_session_pool.h"
[email protected]385a4672009-03-11 22:21:2919#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5720#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5221#include "net/http/http_network_session.h"
22#include "net/http/http_network_transaction.h"
[email protected]0877e3d2009-10-17 22:29:5723#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5224#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5325#include "net/proxy/proxy_config_service_fixed.h"
[email protected]f7984fc62009-06-22 23:26:4426#include "net/socket/client_socket_factory.h"
27#include "net/socket/socket_test_util.h"
28#include "net/socket/ssl_client_socket.h"
initial.commit586acc5fe2008-07-26 22:42:5229#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1530#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5231
32//-----------------------------------------------------------------------------
33
[email protected]89ceba9a2009-03-21 03:46:0634namespace net {
35
[email protected]e44de5d2009-06-05 20:12:4536// Helper to manage the lifetimes of the dependencies for a
37// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5938class SessionDependencies {
39 public:
40 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4241 SessionDependencies()
42 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:3743 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:1044 ssl_config_service(new SSLConfigServiceDefaults),
45 flip_session_pool(new FlipSessionPool) {}
[email protected]228ff742009-06-05 01:19:5946
47 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4548 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4249 : host_resolver(new MockHostResolver),
50 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1051 ssl_config_service(new SSLConfigServiceDefaults),
52 flip_session_pool(new FlipSessionPool) {}
[email protected]228ff742009-06-05 01:19:5953
[email protected]a2c2fb92009-07-18 07:31:0454 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0955 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4256 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5957 MockClientSocketFactory socket_factory;
[email protected]d1eda932009-11-04 01:03:1058 scoped_refptr<FlipSessionPool> flip_session_pool;
[email protected]228ff742009-06-05 01:19:5959};
60
[email protected]1c773ea12009-04-28 19:58:4261ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5062 net::ProxyConfig proxy_config;
63 proxy_config.proxy_rules.ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3964 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5365}
66
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,
74 session_deps->flip_session_pool);
[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]ff007e162009-05-23 09:13:1594 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
95 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:5296
[email protected]228ff742009-06-05 01:19:5997 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:4098 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:4399 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52100
[email protected]ff007e162009-05-23 09:13:15101 HttpRequestInfo request;
102 request.method = "GET";
103 request.url = GURL("http://www.google.com/");
104 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52105
[email protected]5ecc992a42009-11-11 01:41:59106 StaticSocketDataProvider data(data_reads, NULL);
107 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52108
[email protected]ff007e162009-05-23 09:13:15109 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52110
[email protected]684970b2009-08-14 04:54:46111 int rv = trans->Start(&request, &callback, NULL);
[email protected]ff007e162009-05-23 09:13:15112 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52113
[email protected]ff007e162009-05-23 09:13:15114 out.rv = callback.WaitForResult();
115 if (out.rv != OK)
116 return out;
117
118 const HttpResponseInfo* response = trans->GetResponseInfo();
119 EXPECT_TRUE(response != NULL);
120
121 EXPECT_TRUE(response->headers != NULL);
122 out.status_line = response->headers->GetStatusLine();
123
124 rv = ReadTransaction(trans.get(), &out.response_data);
125 EXPECT_EQ(OK, rv);
126
[email protected]aecfbf22008-10-16 02:02:47127 return out;
[email protected]ff007e162009-05-23 09:13:15128 }
initial.commit586acc5fe2008-07-26 22:42:52129
[email protected]ff007e162009-05-23 09:13:15130 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
131 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52132
[email protected]ff007e162009-05-23 09:13:15133 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15134};
[email protected]231d5a32008-09-13 00:45:27135
[email protected]15a5ccf82008-10-23 19:57:43136// Fill |str| with a long header list that consumes >= |size| bytes.
137void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19138 const char* row =
139 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
140 const int sizeof_row = strlen(row);
141 const int num_rows = static_cast<int>(
142 ceil(static_cast<float>(size) / sizeof_row));
143 const int sizeof_data = num_rows * sizeof_row;
144 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43145 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51146
[email protected]4ddaf2502008-10-23 18:26:19147 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43148 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19149}
150
[email protected]385a4672009-03-11 22:21:29151// Alternative functions that eliminate randomness and dependency on the local
152// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20153void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29154 static const uint8 bytes[] = {
155 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
156 };
157 static size_t current_byte = 0;
158 for (size_t i = 0; i < n; ++i) {
159 output[i] = bytes[current_byte++];
160 current_byte %= arraysize(bytes);
161 }
162}
163
[email protected]fe2bc6a2009-03-23 16:52:20164void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29165 static const uint8 bytes[] = {
166 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
167 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
168 };
169 static size_t current_byte = 0;
170 for (size_t i = 0; i < n; ++i) {
171 output[i] = bytes[current_byte++];
172 current_byte %= arraysize(bytes);
173 }
174}
175
[email protected]fe2bc6a2009-03-23 16:52:20176std::string MockGetHostName() {
177 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29178}
179
[email protected]a937a06d2009-08-19 21:19:24180class CaptureGroupNameSocketPool : public TCPClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31181 public:
[email protected]100d5fb92009-12-21 21:08:35182 CaptureGroupNameSocketPool() : TCPClientSocketPool(0, 0, NULL, NULL, NULL) {}
[email protected]d80a4322009-08-14 07:07:49183 const std::string last_group_name_received() const {
184 return last_group_name_;
185 }
186
[email protected]684970b2009-08-14 04:54:46187 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49188 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31189 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31190 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46191 CompletionCallback* callback,
192 LoadLog* load_log) {
[email protected]04e5be32009-06-26 20:00:31193 last_group_name_ = group_name;
194 return ERR_IO_PENDING;
195 }
[email protected]04e5be32009-06-26 20:00:31196 virtual void CancelRequest(const std::string& group_name,
197 const ClientSocketHandle* handle) { }
198 virtual void ReleaseSocket(const std::string& group_name,
199 ClientSocket* socket) {}
200 virtual void CloseIdleSockets() {}
201 virtual HostResolver* GetHostResolver() const {
202 return NULL;
203 }
204 virtual int IdleSocketCount() const {
205 return 0;
206 }
207 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
208 return 0;
209 }
210 virtual LoadState GetLoadState(const std::string& group_name,
211 const ClientSocketHandle* handle) const {
212 return LOAD_STATE_IDLE;
213 }
[email protected]d80a4322009-08-14 07:07:49214
215 private:
[email protected]04e5be32009-06-26 20:00:31216 std::string last_group_name_;
217};
218
[email protected]231d5a32008-09-13 00:45:27219//-----------------------------------------------------------------------------
220
221TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59222 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40223 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43224 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27225}
226
227TEST_F(HttpNetworkTransactionTest, SimpleGET) {
228 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35229 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
230 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42231 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27232 };
[email protected]231d5a32008-09-13 00:45:27233 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42234 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27235 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
236 EXPECT_EQ("hello world", out.response_data);
237}
238
239// Response with no status line.
240TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
241 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35242 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42243 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27244 };
[email protected]231d5a32008-09-13 00:45:27245 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42246 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27247 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
248 EXPECT_EQ("hello world", out.response_data);
249}
250
251// Allow up to 4 bytes of junk to precede status line.
252TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
253 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35254 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42255 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27256 };
257 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42258 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27259 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
260 EXPECT_EQ("DATA", out.response_data);
261}
262
263// Allow up to 4 bytes of junk to precede status line.
264TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
265 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35266 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42267 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27268 };
269 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42270 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27271 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
272 EXPECT_EQ("DATA", out.response_data);
273}
274
275// Beyond 4 bytes of slop and it should fail to find a status line.
276TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
277 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35278 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42279 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27280 };
281 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42282 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25283 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
284 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27285}
286
287// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
288TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
289 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35290 MockRead("\n"),
291 MockRead("\n"),
292 MockRead("Q"),
293 MockRead("J"),
294 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42295 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27296 };
297 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42298 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27299 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
300 EXPECT_EQ("DATA", out.response_data);
301}
302
303// Close the connection before enough bytes to have a status line.
304TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
305 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35306 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42307 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27308 };
309 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42310 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27311 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
312 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52313}
314
[email protected]f9d44aa2008-09-23 23:57:17315// Simulate a 204 response, lacking a Content-Length header, sent over a
316// persistent connection. The response should still terminate since a 204
317// cannot have a response body.
318TEST_F(HttpNetworkTransactionTest, StopsReading204) {
319 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35320 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
321 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42322 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17323 };
324 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42325 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17326 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
327 EXPECT_EQ("", out.response_data);
328}
329
[email protected]0877e3d2009-10-17 22:29:57330// A simple request using chunked encoding with some extra data after.
331// (Like might be seen in a pipelined response.)
332TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
333 MockRead data_reads[] = {
334 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
335 MockRead("5\r\nHello\r\n"),
336 MockRead("1\r\n"),
337 MockRead(" \r\n"),
338 MockRead("5\r\nworld\r\n"),
339 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
340 MockRead(false, OK),
341 };
342 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
343 EXPECT_EQ(OK, out.rv);
344 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
345 EXPECT_EQ("Hello world", out.response_data);
346}
347
[email protected]ef0faf2e72009-03-05 23:27:23348// Do a request using the HEAD method. Verify that we don't try to read the
349// message body (since HEAD has none).
350TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59351 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40352 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43353 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23354
[email protected]1c773ea12009-04-28 19:58:42355 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23356 request.method = "HEAD";
357 request.url = GURL("http://www.google.com/");
358 request.load_flags = 0;
359
360 MockWrite data_writes1[] = {
361 MockWrite("HEAD / HTTP/1.1\r\n"
362 "Host: www.google.com\r\n"
363 "Connection: keep-alive\r\n"
364 "Content-Length: 0\r\n\r\n"),
365 };
366 MockRead data_reads1[] = {
367 MockRead("HTTP/1.1 404 Not Found\r\n"),
368 MockRead("Server: Blah\r\n"),
369 MockRead("Content-Length: 1234\r\n\r\n"),
370
371 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42372 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23373 };
374
[email protected]5ecc992a42009-11-11 01:41:59375 StaticSocketDataProvider data1(data_reads1, data_writes1);
376 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23377
378 TestCompletionCallback callback1;
379
[email protected]684970b2009-08-14 04:54:46380 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42381 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23382
383 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42384 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23385
[email protected]1c773ea12009-04-28 19:58:42386 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23387 EXPECT_FALSE(response == NULL);
388
389 // Check that the headers got parsed.
390 EXPECT_TRUE(response->headers != NULL);
391 EXPECT_EQ(1234, response->headers->GetContentLength());
392 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
393
394 std::string server_header;
395 void* iter = NULL;
396 bool has_server_header = response->headers->EnumerateHeader(
397 &iter, "Server", &server_header);
398 EXPECT_TRUE(has_server_header);
399 EXPECT_EQ("Blah", server_header);
400
401 // Reading should give EOF right away, since there is no message body
402 // (despite non-zero content-length).
403 std::string response_data;
404 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42405 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23406 EXPECT_EQ("", response_data);
407}
408
initial.commit586acc5fe2008-07-26 22:42:52409TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59410 SessionDependencies session_deps;
411 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52412
413 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35414 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
415 MockRead("hello"),
416 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
417 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42418 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52419 };
[email protected]5ecc992a42009-11-11 01:41:59420 StaticSocketDataProvider data(data_reads, NULL);
421 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52422
423 const char* kExpectedResponseData[] = {
424 "hello", "world"
425 };
426
427 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43428 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52429
[email protected]1c773ea12009-04-28 19:58:42430 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52431 request.method = "GET";
432 request.url = GURL("http://www.google.com/");
433 request.load_flags = 0;
434
435 TestCompletionCallback callback;
436
[email protected]684970b2009-08-14 04:54:46437 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42438 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52439
440 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42441 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52442
[email protected]1c773ea12009-04-28 19:58:42443 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52444 EXPECT_TRUE(response != NULL);
445
446 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25447 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52448
449 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57450 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42451 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25452 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52453 }
454}
455
456TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59457 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40458 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43459 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52460
[email protected]1c773ea12009-04-28 19:58:42461 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52462 request.method = "POST";
463 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42464 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52465 request.upload_data->AppendBytes("foo", 3);
466 request.load_flags = 0;
467
468 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35469 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
470 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
471 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42472 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52473 };
[email protected]5ecc992a42009-11-11 01:41:59474 StaticSocketDataProvider data(data_reads, NULL);
475 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52476
477 TestCompletionCallback callback;
478
[email protected]684970b2009-08-14 04:54:46479 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42480 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52481
482 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42483 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52484
[email protected]1c773ea12009-04-28 19:58:42485 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52486 EXPECT_TRUE(response != NULL);
487
488 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25489 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52490
491 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57492 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42493 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25494 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52495}
496
[email protected]3a2d3662009-03-27 03:49:14497// This test is almost the same as Ignores100 above, but the response contains
498// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57499// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14500TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59501 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40502 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43503 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14504
[email protected]1c773ea12009-04-28 19:58:42505 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14506 request.method = "GET";
507 request.url = GURL("http://www.foo.com/");
508 request.load_flags = 0;
509
510 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57511 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
512 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14513 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42514 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14515 };
[email protected]5ecc992a42009-11-11 01:41:59516 StaticSocketDataProvider data(data_reads, NULL);
517 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14518
519 TestCompletionCallback callback;
520
[email protected]684970b2009-08-14 04:54:46521 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42522 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14523
524 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42525 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14526
[email protected]1c773ea12009-04-28 19:58:42527 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14528 EXPECT_TRUE(response != NULL);
529
530 EXPECT_TRUE(response->headers != NULL);
531 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
532
533 std::string response_data;
534 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42535 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14536 EXPECT_EQ("hello world", response_data);
537}
538
[email protected]ee9410e72010-01-07 01:42:38539TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
540 SessionDependencies session_deps;
541 scoped_ptr<HttpTransaction> trans(
542 new HttpNetworkTransaction(CreateSession(&session_deps)));
543
544 HttpRequestInfo request;
545 request.method = "POST";
546 request.url = GURL("http://www.foo.com/");
547 request.load_flags = 0;
548
549 MockRead data_reads[] = {
550 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
551 MockRead(true, 0),
552 };
553 StaticSocketDataProvider data(data_reads, NULL);
554 session_deps.socket_factory.AddSocketDataProvider(&data);
555
556 TestCompletionCallback callback;
557
558 int rv = trans->Start(&request, &callback, NULL);
559 EXPECT_EQ(ERR_IO_PENDING, rv);
560
561 rv = callback.WaitForResult();
562 EXPECT_EQ(OK, rv);
563
564 std::string response_data;
565 rv = ReadTransaction(trans.get(), &response_data);
566 EXPECT_EQ(OK, rv);
567 EXPECT_EQ("", response_data);
568}
569
570TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
571 SessionDependencies session_deps;
572 scoped_ptr<HttpTransaction> trans(
573 new HttpNetworkTransaction(CreateSession(&session_deps)));
574
575 HttpRequestInfo request;
576 request.method = "POST";
577 request.url = GURL("http://www.foo.com/");
578 request.load_flags = 0;
579
580 MockRead data_reads[] = {
581 MockRead(true, 0),
582 };
583 StaticSocketDataProvider data(data_reads, NULL);
584 session_deps.socket_factory.AddSocketDataProvider(&data);
585
586 TestCompletionCallback callback;
587
588 int rv = trans->Start(&request, &callback, NULL);
589 EXPECT_EQ(ERR_IO_PENDING, rv);
590
591 rv = callback.WaitForResult();
592 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
593}
594
[email protected]3d2a59b2008-09-26 19:44:25595// read_failure specifies a read failure that should cause the network
596// transaction to resend the request.
597void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
598 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59599 SessionDependencies session_deps;
600 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52601
[email protected]1c773ea12009-04-28 19:58:42602 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52603 request.method = "GET";
604 request.url = GURL("http://www.foo.com/");
605 request.load_flags = 0;
606
607 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35608 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
609 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25610 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52611 };
[email protected]5ecc992a42009-11-11 01:41:59612 StaticSocketDataProvider data1(data1_reads, NULL);
613 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52614
615 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35616 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
617 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42618 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52619 };
[email protected]5ecc992a42009-11-11 01:41:59620 StaticSocketDataProvider data2(data2_reads, NULL);
621 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52622
623 const char* kExpectedResponseData[] = {
624 "hello", "world"
625 };
626
627 for (int i = 0; i < 2; ++i) {
628 TestCompletionCallback callback;
629
[email protected]5695b8c2009-09-30 21:36:43630 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52631
[email protected]684970b2009-08-14 04:54:46632 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42633 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52634
635 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42636 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52637
[email protected]1c773ea12009-04-28 19:58:42638 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52639 EXPECT_TRUE(response != NULL);
640
641 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25642 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52643
644 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57645 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42646 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25647 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52648 }
649}
[email protected]3d2a59b2008-09-26 19:44:25650
651TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42652 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25653 KeepAliveConnectionResendRequestTest(read_failure);
654}
655
656TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42657 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25658 KeepAliveConnectionResendRequestTest(read_failure);
659}
660
661TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59662 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40663 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43664 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25665
[email protected]1c773ea12009-04-28 19:58:42666 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25667 request.method = "GET";
668 request.url = GURL("http://www.google.com/");
669 request.load_flags = 0;
670
671 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42672 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35673 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
674 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42675 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25676 };
[email protected]5ecc992a42009-11-11 01:41:59677 StaticSocketDataProvider data(data_reads, NULL);
678 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25679
680 TestCompletionCallback callback;
681
[email protected]684970b2009-08-14 04:54:46682 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42683 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25684
685 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42686 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25687
[email protected]1c773ea12009-04-28 19:58:42688 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25689 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25690}
691
692// What do various browsers do when the server closes a non-keepalive
693// connection without sending any response header or body?
694//
695// IE7: error page
696// Safari 3.1.2 (Windows): error page
697// Firefox 3.0.1: blank page
698// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42699// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
700// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25701TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
702 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42703 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35704 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
705 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42706 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25707 };
708 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42709 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25710}
[email protected]038e9a32008-10-08 22:40:16711
712// Test the request-challenge-retry sequence for basic auth.
713// (basic auth is the easiest to mock, because it has no randomness).
714TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59715 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40716 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43717 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16718
[email protected]1c773ea12009-04-28 19:58:42719 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16720 request.method = "GET";
721 request.url = GURL("http://www.google.com/");
722 request.load_flags = 0;
723
[email protected]f9ee6b52008-11-08 06:46:23724 MockWrite data_writes1[] = {
725 MockWrite("GET / HTTP/1.1\r\n"
726 "Host: www.google.com\r\n"
727 "Connection: keep-alive\r\n\r\n"),
728 };
729
[email protected]038e9a32008-10-08 22:40:16730 MockRead data_reads1[] = {
731 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
732 // Give a couple authenticate options (only the middle one is actually
733 // supported).
[email protected]22927ad2009-09-21 19:56:19734 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16735 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
736 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
737 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
738 // Large content-length -- won't matter, as connection will be reset.
739 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42740 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16741 };
742
743 // After calling trans->RestartWithAuth(), this is the request we should
744 // be issuing -- the final header line contains the credentials.
745 MockWrite data_writes2[] = {
746 MockWrite("GET / HTTP/1.1\r\n"
747 "Host: www.google.com\r\n"
748 "Connection: keep-alive\r\n"
749 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
750 };
751
752 // Lastly, the server responds with the actual content.
753 MockRead data_reads2[] = {
754 MockRead("HTTP/1.0 200 OK\r\n"),
755 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
756 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42757 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16758 };
759
[email protected]5ecc992a42009-11-11 01:41:59760 StaticSocketDataProvider data1(data_reads1, data_writes1);
761 StaticSocketDataProvider data2(data_reads2, data_writes2);
762 session_deps.socket_factory.AddSocketDataProvider(&data1);
763 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16764
765 TestCompletionCallback callback1;
766
[email protected]684970b2009-08-14 04:54:46767 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42768 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16769
770 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42771 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16772
[email protected]1c773ea12009-04-28 19:58:42773 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16774 EXPECT_FALSE(response == NULL);
775
776 // The password prompt info should have been set in response->auth_challenge.
777 EXPECT_FALSE(response->auth_challenge.get() == NULL);
778
[email protected]71e4573a2009-05-21 22:03:00779 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16780 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
781 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
782
783 TestCompletionCallback callback2;
784
785 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42786 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16787
788 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42789 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16790
791 response = trans->GetResponseInfo();
792 EXPECT_FALSE(response == NULL);
793 EXPECT_TRUE(response->auth_challenge.get() == NULL);
794 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16795}
796
[email protected]861fcd52009-08-26 02:33:46797TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
798 SessionDependencies session_deps;
799 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43800 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46801
802 HttpRequestInfo request;
803 request.method = "GET";
804 request.url = GURL("http://www.google.com/");
805 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
806
807 MockWrite data_writes[] = {
808 MockWrite("GET / HTTP/1.1\r\n"
809 "Host: www.google.com\r\n"
810 "Connection: keep-alive\r\n\r\n"),
811 };
812
813 MockRead data_reads[] = {
814 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
815 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
816 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
817 // Large content-length -- won't matter, as connection will be reset.
818 MockRead("Content-Length: 10000\r\n\r\n"),
819 MockRead(false, ERR_FAILED),
820 };
821
[email protected]5ecc992a42009-11-11 01:41:59822 StaticSocketDataProvider data(data_reads, data_writes);
823 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46824 TestCompletionCallback callback;
825
826 int rv = trans->Start(&request, &callback, NULL);
827 EXPECT_EQ(ERR_IO_PENDING, rv);
828
829 rv = callback.WaitForResult();
830 EXPECT_EQ(0, rv);
831
832 const HttpResponseInfo* response = trans->GetResponseInfo();
833 ASSERT_FALSE(response == NULL);
834 EXPECT_TRUE(response->auth_challenge.get() == NULL);
835}
836
[email protected]2d2697f92009-02-18 21:00:32837// Test the request-challenge-retry sequence for basic auth, over a keep-alive
838// connection.
839TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59840 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40841 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43842 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32843
[email protected]1c773ea12009-04-28 19:58:42844 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32845 request.method = "GET";
846 request.url = GURL("http://www.google.com/");
847 request.load_flags = 0;
848
849 MockWrite data_writes1[] = {
850 MockWrite("GET / HTTP/1.1\r\n"
851 "Host: www.google.com\r\n"
852 "Connection: keep-alive\r\n\r\n"),
853
854 // After calling trans->RestartWithAuth(), this is the request we should
855 // be issuing -- the final header line contains the credentials.
856 MockWrite("GET / HTTP/1.1\r\n"
857 "Host: www.google.com\r\n"
858 "Connection: keep-alive\r\n"
859 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
860 };
861
862 MockRead data_reads1[] = {
863 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
864 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
865 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
866 MockRead("Content-Length: 14\r\n\r\n"),
867 MockRead("Unauthorized\r\n"),
868
869 // Lastly, the server responds with the actual content.
870 MockRead("HTTP/1.1 200 OK\r\n"),
871 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
872 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42873 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32874 };
875
[email protected]5ecc992a42009-11-11 01:41:59876 StaticSocketDataProvider data1(data_reads1, data_writes1);
877 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32878
879 TestCompletionCallback callback1;
880
[email protected]684970b2009-08-14 04:54:46881 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42882 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32883
884 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42885 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32886
[email protected]1c773ea12009-04-28 19:58:42887 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32888 EXPECT_FALSE(response == NULL);
889
890 // The password prompt info should have been set in response->auth_challenge.
891 EXPECT_FALSE(response->auth_challenge.get() == NULL);
892
[email protected]71e4573a2009-05-21 22:03:00893 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32894 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
895 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
896
897 TestCompletionCallback callback2;
898
899 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42900 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32901
902 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42903 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32904
905 response = trans->GetResponseInfo();
906 EXPECT_FALSE(response == NULL);
907 EXPECT_TRUE(response->auth_challenge.get() == NULL);
908 EXPECT_EQ(100, response->headers->GetContentLength());
909}
910
911// Test the request-challenge-retry sequence for basic auth, over a keep-alive
912// connection and with no response body to drain.
913TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59914 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40915 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43916 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32917
[email protected]1c773ea12009-04-28 19:58:42918 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32919 request.method = "GET";
920 request.url = GURL("http://www.google.com/");
921 request.load_flags = 0;
922
923 MockWrite data_writes1[] = {
924 MockWrite("GET / HTTP/1.1\r\n"
925 "Host: www.google.com\r\n"
926 "Connection: keep-alive\r\n\r\n"),
927
928 // After calling trans->RestartWithAuth(), this is the request we should
929 // be issuing -- the final header line contains the credentials.
930 MockWrite("GET / HTTP/1.1\r\n"
931 "Host: www.google.com\r\n"
932 "Connection: keep-alive\r\n"
933 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
934 };
935
[email protected]2d2697f92009-02-18 21:00:32936 MockRead data_reads1[] = {
937 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
938 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:31939 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:32940
941 // Lastly, the server responds with the actual content.
942 MockRead("HTTP/1.1 200 OK\r\n"),
943 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
944 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42945 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32946 };
947
[email protected]5ecc992a42009-11-11 01:41:59948 StaticSocketDataProvider data1(data_reads1, data_writes1);
949 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32950
951 TestCompletionCallback callback1;
952
[email protected]684970b2009-08-14 04:54:46953 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42954 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32955
956 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42957 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32958
[email protected]1c773ea12009-04-28 19:58:42959 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32960 EXPECT_FALSE(response == NULL);
961
962 // The password prompt info should have been set in response->auth_challenge.
963 EXPECT_FALSE(response->auth_challenge.get() == NULL);
964
[email protected]71e4573a2009-05-21 22:03:00965 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32966 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
967 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
968
969 TestCompletionCallback callback2;
970
971 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42972 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32973
974 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42975 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32976
977 response = trans->GetResponseInfo();
978 EXPECT_FALSE(response == NULL);
979 EXPECT_TRUE(response->auth_challenge.get() == NULL);
980 EXPECT_EQ(100, response->headers->GetContentLength());
981}
982
983// Test the request-challenge-retry sequence for basic auth, over a keep-alive
984// connection and with a large response body to drain.
985TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:59986 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40987 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43988 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32989
[email protected]1c773ea12009-04-28 19:58:42990 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32991 request.method = "GET";
992 request.url = GURL("http://www.google.com/");
993 request.load_flags = 0;
994
995 MockWrite data_writes1[] = {
996 MockWrite("GET / HTTP/1.1\r\n"
997 "Host: www.google.com\r\n"
998 "Connection: keep-alive\r\n\r\n"),
999
1000 // After calling trans->RestartWithAuth(), this is the request we should
1001 // be issuing -- the final header line contains the credentials.
1002 MockWrite("GET / HTTP/1.1\r\n"
1003 "Host: www.google.com\r\n"
1004 "Connection: keep-alive\r\n"
1005 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1006 };
1007
1008 // Respond with 5 kb of response body.
1009 std::string large_body_string("Unauthorized");
1010 large_body_string.append(5 * 1024, ' ');
1011 large_body_string.append("\r\n");
1012
1013 MockRead data_reads1[] = {
1014 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1015 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1016 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1017 // 5134 = 12 + 5 * 1024 + 2
1018 MockRead("Content-Length: 5134\r\n\r\n"),
1019 MockRead(true, large_body_string.data(), large_body_string.size()),
1020
1021 // Lastly, the server responds with the actual content.
1022 MockRead("HTTP/1.1 200 OK\r\n"),
1023 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1024 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421025 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321026 };
1027
[email protected]5ecc992a42009-11-11 01:41:591028 StaticSocketDataProvider data1(data_reads1, data_writes1);
1029 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321030
1031 TestCompletionCallback callback1;
1032
[email protected]684970b2009-08-14 04:54:461033 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421034 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321035
1036 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421037 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321038
[email protected]1c773ea12009-04-28 19:58:421039 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321040 EXPECT_FALSE(response == NULL);
1041
1042 // The password prompt info should have been set in response->auth_challenge.
1043 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1044
[email protected]71e4573a2009-05-21 22:03:001045 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321046 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1047 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1048
1049 TestCompletionCallback callback2;
1050
1051 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421052 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321053
1054 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421055 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321056
1057 response = trans->GetResponseInfo();
1058 EXPECT_FALSE(response == NULL);
1059 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1060 EXPECT_EQ(100, response->headers->GetContentLength());
1061}
1062
1063// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311064// connection, but the server gets impatient and closes the connection.
1065TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1066 SessionDependencies session_deps;
1067 scoped_ptr<HttpTransaction> trans(
1068 new HttpNetworkTransaction(CreateSession(&session_deps)));
1069
1070 HttpRequestInfo request;
1071 request.method = "GET";
1072 request.url = GURL("http://www.google.com/");
1073 request.load_flags = 0;
1074
1075 MockWrite data_writes1[] = {
1076 MockWrite("GET / HTTP/1.1\r\n"
1077 "Host: www.google.com\r\n"
1078 "Connection: keep-alive\r\n\r\n"),
1079 // This simulates the seemingly successful write to a closed connection
1080 // if the bug is not fixed.
1081 MockWrite("GET / HTTP/1.1\r\n"
1082 "Host: www.google.com\r\n"
1083 "Connection: keep-alive\r\n"
1084 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1085 };
1086
1087 MockRead data_reads1[] = {
1088 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1089 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1090 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1091 MockRead("Content-Length: 14\r\n\r\n"),
1092 // Tell MockTCPClientSocket to simulate the server closing the connection.
1093 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1094 MockRead("Unauthorized\r\n"),
1095 MockRead(false, OK), // The server closes the connection.
1096 };
1097
1098 // After calling trans->RestartWithAuth(), this is the request we should
1099 // be issuing -- the final header line contains the credentials.
1100 MockWrite data_writes2[] = {
1101 MockWrite("GET / HTTP/1.1\r\n"
1102 "Host: www.google.com\r\n"
1103 "Connection: keep-alive\r\n"
1104 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1105 };
1106
1107 // Lastly, the server responds with the actual content.
1108 MockRead data_reads2[] = {
1109 MockRead("HTTP/1.1 200 OK\r\n"),
1110 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1111 MockRead("Content-Length: 100\r\n\r\n"),
1112 MockRead(false, OK),
1113 };
1114
1115 StaticSocketDataProvider data1(data_reads1, data_writes1);
1116 StaticSocketDataProvider data2(data_reads2, data_writes2);
1117 session_deps.socket_factory.AddSocketDataProvider(&data1);
1118 session_deps.socket_factory.AddSocketDataProvider(&data2);
1119
1120 TestCompletionCallback callback1;
1121
1122 int rv = trans->Start(&request, &callback1, NULL);
1123 EXPECT_EQ(ERR_IO_PENDING, rv);
1124
1125 rv = callback1.WaitForResult();
1126 EXPECT_EQ(OK, rv);
1127
1128 const HttpResponseInfo* response = trans->GetResponseInfo();
1129 EXPECT_FALSE(response == NULL);
1130
1131 // The password prompt info should have been set in response->auth_challenge.
1132 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1133
1134 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1135 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1136 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1137
1138 TestCompletionCallback callback2;
1139
1140 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1141 EXPECT_EQ(ERR_IO_PENDING, rv);
1142
1143 rv = callback2.WaitForResult();
1144 EXPECT_EQ(OK, rv);
1145
1146 response = trans->GetResponseInfo();
1147 ASSERT_FALSE(response == NULL);
1148 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1149 EXPECT_EQ(100, response->headers->GetContentLength());
1150}
1151
1152// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321153// proxy connection, when setting up an SSL tunnel.
1154TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1155 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591156 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1157 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321158
[email protected]5695b8c2009-09-30 21:36:431159 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321160
[email protected]1c773ea12009-04-28 19:58:421161 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321162 request.method = "GET";
1163 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461164 // Ensure that proxy authentication is attempted even
1165 // when the no authentication data flag is set.
1166 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321167
1168 // Since we have proxy, should try to establish tunnel.
1169 MockWrite data_writes1[] = {
1170 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451171 "Host: www.google.com\r\n"
1172 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321173
1174 // After calling trans->RestartWithAuth(), this is the request we should
1175 // be issuing -- the final header line contains the credentials.
1176 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1177 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451178 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321179 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1180 };
1181
1182 // The proxy responds to the connect with a 407, using a persistent
1183 // connection.
1184 MockRead data_reads1[] = {
1185 // No credentials.
1186 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1187 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1188 MockRead("Content-Length: 10\r\n\r\n"),
1189 MockRead("0123456789"),
1190
1191 // Wrong credentials (wrong password).
1192 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1193 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1194 MockRead("Content-Length: 10\r\n\r\n"),
1195 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421196 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321197 };
1198
[email protected]5ecc992a42009-11-11 01:41:591199 StaticSocketDataProvider data1(data_reads1, data_writes1);
1200 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321201
1202 TestCompletionCallback callback1;
1203
[email protected]684970b2009-08-14 04:54:461204 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421205 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321206
1207 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421208 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321209
[email protected]1c773ea12009-04-28 19:58:421210 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321211 EXPECT_FALSE(response == NULL);
1212
1213 EXPECT_TRUE(response->headers->IsKeepAlive());
1214 EXPECT_EQ(407, response->headers->response_code());
1215 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421216 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321217
1218 // The password prompt info should have been set in response->auth_challenge.
1219 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1220
[email protected]71e4573a2009-05-21 22:03:001221 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321222 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1223 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1224
1225 TestCompletionCallback callback2;
1226
1227 // Wrong password (should be "bar").
1228 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421229 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321230
1231 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421232 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321233
1234 response = trans->GetResponseInfo();
1235 EXPECT_FALSE(response == NULL);
1236
1237 EXPECT_TRUE(response->headers->IsKeepAlive());
1238 EXPECT_EQ(407, response->headers->response_code());
1239 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421240 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321241
1242 // The password prompt info should have been set in response->auth_challenge.
1243 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1244
[email protected]71e4573a2009-05-21 22:03:001245 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321246 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1247 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1248}
1249
[email protected]a8e9b162009-03-12 00:06:441250// Test that we don't read the response body when we fail to establish a tunnel,
1251// even if the user cancels the proxy's auth attempt.
1252TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1253 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591254 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441255
[email protected]e44de5d2009-06-05 20:12:451256 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441257
[email protected]5695b8c2009-09-30 21:36:431258 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441259
[email protected]1c773ea12009-04-28 19:58:421260 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441261 request.method = "GET";
1262 request.url = GURL("https://www.google.com/");
1263 request.load_flags = 0;
1264
1265 // Since we have proxy, should try to establish tunnel.
1266 MockWrite data_writes[] = {
1267 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451268 "Host: www.google.com\r\n"
1269 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441270 };
1271
1272 // The proxy responds to the connect with a 407.
1273 MockRead data_reads[] = {
1274 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1275 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1276 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421277 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441278 };
1279
[email protected]5ecc992a42009-11-11 01:41:591280 StaticSocketDataProvider data(data_reads, data_writes);
1281 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441282
1283 TestCompletionCallback callback;
1284
[email protected]684970b2009-08-14 04:54:461285 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421286 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441287
1288 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421289 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441290
[email protected]1c773ea12009-04-28 19:58:421291 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441292 EXPECT_FALSE(response == NULL);
1293
1294 EXPECT_TRUE(response->headers->IsKeepAlive());
1295 EXPECT_EQ(407, response->headers->response_code());
1296 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421297 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441298
1299 std::string response_data;
1300 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421301 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441302}
1303
[email protected]ff007e162009-05-23 09:13:151304void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081305 const MockRead& status, int expected_status) {
1306 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591307 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081308
[email protected]228ff742009-06-05 01:19:591309 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081310
[email protected]5695b8c2009-09-30 21:36:431311 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081312
[email protected]1c773ea12009-04-28 19:58:421313 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081314 request.method = "GET";
1315 request.url = GURL("https://www.google.com/");
1316 request.load_flags = 0;
1317
1318 // Since we have proxy, should try to establish tunnel.
1319 MockWrite data_writes[] = {
1320 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451321 "Host: www.google.com\r\n"
1322 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081323 };
1324
1325 MockRead data_reads[] = {
1326 status,
1327 MockRead("Content-Length: 10\r\n\r\n"),
1328 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421329 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081330 };
1331
[email protected]5ecc992a42009-11-11 01:41:591332 StaticSocketDataProvider data(data_reads, data_writes);
1333 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081334
1335 TestCompletionCallback callback;
1336
[email protected]684970b2009-08-14 04:54:461337 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421338 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081339
1340 rv = callback.WaitForResult();
1341 EXPECT_EQ(expected_status, rv);
1342}
1343
[email protected]ff007e162009-05-23 09:13:151344void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081345 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421346 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081347}
1348
1349TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1350 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1351}
1352
1353TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1354 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1355}
1356
1357TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1358 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1359}
1360
1361TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1362 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1363}
1364
1365TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1366 ConnectStatusHelper(
1367 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1368}
1369
1370TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1371 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1372}
1373
1374TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1375 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1376}
1377
1378TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1379 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1380}
1381
1382TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1383 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1384}
1385
1386TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1387 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1388}
1389
1390TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1391 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1392}
1393
1394TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1395 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1396}
1397
1398TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1399 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1400}
1401
1402TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1403 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1404}
1405
1406TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1407 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1408}
1409
1410TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1411 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1412}
1413
1414TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1415 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1416}
1417
1418TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1419 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1420}
1421
1422TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1423 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1424}
1425
1426TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1427 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1428}
1429
1430TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1431 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1432}
1433
1434TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1435 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1436}
1437
1438TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1439 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1440}
1441
1442TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1443 ConnectStatusHelperWithExpectedStatus(
1444 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421445 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081446}
1447
1448TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1449 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1450}
1451
1452TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1453 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1454}
1455
1456TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1457 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1458}
1459
1460TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1461 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1462}
1463
1464TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1465 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1466}
1467
1468TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1469 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1470}
1471
1472TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1473 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1474}
1475
1476TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1477 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1478}
1479
1480TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1481 ConnectStatusHelper(
1482 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1483}
1484
1485TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1486 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1487}
1488
1489TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1490 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1491}
1492
1493TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1494 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1495}
1496
1497TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1498 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1499}
1500
1501TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1502 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1503}
1504
1505TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1506 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1507}
1508
1509TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1510 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1511}
1512
[email protected]038e9a32008-10-08 22:40:161513// Test the flow when both the proxy server AND origin server require
1514// authentication. Again, this uses basic auth for both since that is
1515// the simplest to mock.
1516TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591517 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011518
[email protected]038e9a32008-10-08 22:40:161519 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421520 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431521 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161522
[email protected]1c773ea12009-04-28 19:58:421523 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161524 request.method = "GET";
1525 request.url = GURL("http://www.google.com/");
1526 request.load_flags = 0;
1527
[email protected]f9ee6b52008-11-08 06:46:231528 MockWrite data_writes1[] = {
1529 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1530 "Host: www.google.com\r\n"
1531 "Proxy-Connection: keep-alive\r\n\r\n"),
1532 };
1533
[email protected]038e9a32008-10-08 22:40:161534 MockRead data_reads1[] = {
1535 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1536 // Give a couple authenticate options (only the middle one is actually
1537 // supported).
[email protected]22927ad2009-09-21 19:56:191538 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161539 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1540 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1541 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1542 // Large content-length -- won't matter, as connection will be reset.
1543 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421544 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161545 };
1546
1547 // After calling trans->RestartWithAuth() the first time, this is the
1548 // request we should be issuing -- the final header line contains the
1549 // proxy's credentials.
1550 MockWrite data_writes2[] = {
1551 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1552 "Host: www.google.com\r\n"
1553 "Proxy-Connection: keep-alive\r\n"
1554 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1555 };
1556
1557 // Now the proxy server lets the request pass through to origin server.
1558 // The origin server responds with a 401.
1559 MockRead data_reads2[] = {
1560 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1561 // Note: We are using the same realm-name as the proxy server. This is
1562 // completely valid, as realms are unique across hosts.
1563 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1564 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1565 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421566 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161567 };
1568
1569 // After calling trans->RestartWithAuth() the second time, we should send
1570 // the credentials for both the proxy and origin server.
1571 MockWrite data_writes3[] = {
1572 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1573 "Host: www.google.com\r\n"
1574 "Proxy-Connection: keep-alive\r\n"
1575 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1576 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1577 };
1578
1579 // Lastly we get the desired content.
1580 MockRead data_reads3[] = {
1581 MockRead("HTTP/1.0 200 OK\r\n"),
1582 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1583 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421584 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161585 };
1586
[email protected]5ecc992a42009-11-11 01:41:591587 StaticSocketDataProvider data1(data_reads1, data_writes1);
1588 StaticSocketDataProvider data2(data_reads2, data_writes2);
1589 StaticSocketDataProvider data3(data_reads3, data_writes3);
1590 session_deps.socket_factory.AddSocketDataProvider(&data1);
1591 session_deps.socket_factory.AddSocketDataProvider(&data2);
1592 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161593
1594 TestCompletionCallback callback1;
1595
[email protected]684970b2009-08-14 04:54:461596 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421597 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161598
1599 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421600 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161601
[email protected]1c773ea12009-04-28 19:58:421602 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161603 EXPECT_FALSE(response == NULL);
1604
1605 // The password prompt info should have been set in response->auth_challenge.
1606 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1607
[email protected]71e4573a2009-05-21 22:03:001608 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161609 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1610 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1611
1612 TestCompletionCallback callback2;
1613
1614 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421615 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161616
1617 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421618 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161619
1620 response = trans->GetResponseInfo();
1621 EXPECT_FALSE(response == NULL);
1622 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1623
[email protected]71e4573a2009-05-21 22:03:001624 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161625 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1626 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1627
1628 TestCompletionCallback callback3;
1629
1630 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421631 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161632
1633 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421634 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161635
1636 response = trans->GetResponseInfo();
1637 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1638 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161639}
[email protected]4ddaf2502008-10-23 18:26:191640
[email protected]ea9dc9a2009-09-05 00:43:321641// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1642// can't hook into its internals to cause it to generate predictable NTLM
1643// authorization headers.
1644#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291645// The NTLM authentication unit tests were generated by capturing the HTTP
1646// requests and responses using Fiddler 2 and inspecting the generated random
1647// bytes in the debugger.
1648
1649// Enter the correct password and authenticate successfully.
1650TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421651 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201652 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591653 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401654 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431655 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241656
[email protected]1c773ea12009-04-28 19:58:421657 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241658 request.method = "GET";
1659 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1660 request.load_flags = 0;
1661
1662 MockWrite data_writes1[] = {
1663 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1664 "Host: 172.22.68.17\r\n"
1665 "Connection: keep-alive\r\n\r\n"),
1666 };
1667
1668 MockRead data_reads1[] = {
1669 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1670 // Negotiate and NTLM are often requested together. We only support NTLM.
1671 MockRead("WWW-Authenticate: Negotiate\r\n"),
1672 MockRead("WWW-Authenticate: NTLM\r\n"),
1673 MockRead("Connection: close\r\n"),
1674 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361675 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241676 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421677 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241678 };
1679
1680 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221681 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241682 // request we should be issuing -- the final header line contains a Type
1683 // 1 message.
1684 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1685 "Host: 172.22.68.17\r\n"
1686 "Connection: keep-alive\r\n"
1687 "Authorization: NTLM "
1688 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1689
1690 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1691 // (the credentials for the origin server). The second request continues
1692 // on the same connection.
1693 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1694 "Host: 172.22.68.17\r\n"
1695 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291696 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1697 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1698 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1699 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1700 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241701 };
1702
1703 MockRead data_reads2[] = {
1704 // The origin server responds with a Type 2 message.
1705 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1706 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291707 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241708 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1709 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1710 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1711 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1712 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1713 "BtAAAAAAA=\r\n"),
1714 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361715 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241716 MockRead("You are not authorized to view this page\r\n"),
1717
1718 // Lastly we get the desired content.
1719 MockRead("HTTP/1.1 200 OK\r\n"),
1720 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1721 MockRead("Content-Length: 13\r\n\r\n"),
1722 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421723 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241724 };
1725
[email protected]5ecc992a42009-11-11 01:41:591726 StaticSocketDataProvider data1(data_reads1, data_writes1);
1727 StaticSocketDataProvider data2(data_reads2, data_writes2);
1728 session_deps.socket_factory.AddSocketDataProvider(&data1);
1729 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241730
1731 TestCompletionCallback callback1;
1732
[email protected]684970b2009-08-14 04:54:461733 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421734 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241735
1736 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421737 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241738
[email protected]0757e7702009-03-27 04:00:221739 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1740 TestCompletionCallback callback2;
1741 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421742 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221743 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421744 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221745 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1746
[email protected]1c773ea12009-04-28 19:58:421747 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241748 EXPECT_FALSE(response == NULL);
1749
1750 // The password prompt info should have been set in response->auth_challenge.
1751 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1752
[email protected]71e4573a2009-05-21 22:03:001753 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241754 EXPECT_EQ(L"", response->auth_challenge->realm);
1755 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1756
[email protected]0757e7702009-03-27 04:00:221757 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241758
[email protected]0757e7702009-03-27 04:00:221759 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421760 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241761
[email protected]0757e7702009-03-27 04:00:221762 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421763 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241764
1765 response = trans->GetResponseInfo();
1766 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1767 EXPECT_EQ(13, response->headers->GetContentLength());
1768}
1769
[email protected]385a4672009-03-11 22:21:291770// Enter a wrong password, and then the correct one.
1771TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421772 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201773 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591774 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401775 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431776 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291777
[email protected]1c773ea12009-04-28 19:58:421778 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291779 request.method = "GET";
1780 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1781 request.load_flags = 0;
1782
1783 MockWrite data_writes1[] = {
1784 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1785 "Host: 172.22.68.17\r\n"
1786 "Connection: keep-alive\r\n\r\n"),
1787 };
1788
1789 MockRead data_reads1[] = {
1790 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1791 // Negotiate and NTLM are often requested together. We only support NTLM.
1792 MockRead("WWW-Authenticate: Negotiate\r\n"),
1793 MockRead("WWW-Authenticate: NTLM\r\n"),
1794 MockRead("Connection: close\r\n"),
1795 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361796 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291797 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421798 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291799 };
1800
1801 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221802 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291803 // request we should be issuing -- the final header line contains a Type
1804 // 1 message.
1805 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1806 "Host: 172.22.68.17\r\n"
1807 "Connection: keep-alive\r\n"
1808 "Authorization: NTLM "
1809 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1810
1811 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1812 // (the credentials for the origin server). The second request continues
1813 // on the same connection.
1814 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1815 "Host: 172.22.68.17\r\n"
1816 "Connection: keep-alive\r\n"
1817 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1818 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1819 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1820 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1821 "4Ww7b7E=\r\n\r\n"),
1822 };
1823
1824 MockRead data_reads2[] = {
1825 // The origin server responds with a Type 2 message.
1826 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1827 MockRead("WWW-Authenticate: NTLM "
1828 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1829 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1830 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1831 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1832 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1833 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1834 "BtAAAAAAA=\r\n"),
1835 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361836 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291837 MockRead("You are not authorized to view this page\r\n"),
1838
1839 // Wrong password.
1840 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1841 MockRead("WWW-Authenticate: Negotiate\r\n"),
1842 MockRead("WWW-Authenticate: NTLM\r\n"),
1843 MockRead("Connection: close\r\n"),
1844 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361845 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291846 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421847 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291848 };
1849
1850 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221851 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291852 // request we should be issuing -- the final header line contains a Type
1853 // 1 message.
1854 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1855 "Host: 172.22.68.17\r\n"
1856 "Connection: keep-alive\r\n"
1857 "Authorization: NTLM "
1858 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1859
1860 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1861 // (the credentials for the origin server). The second request continues
1862 // on the same connection.
1863 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1864 "Host: 172.22.68.17\r\n"
1865 "Connection: keep-alive\r\n"
1866 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1867 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1868 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1869 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1870 "+4MUm7c=\r\n\r\n"),
1871 };
1872
1873 MockRead data_reads3[] = {
1874 // The origin server responds with a Type 2 message.
1875 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1876 MockRead("WWW-Authenticate: NTLM "
1877 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1878 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1879 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1880 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1881 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1882 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1883 "BtAAAAAAA=\r\n"),
1884 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361885 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291886 MockRead("You are not authorized to view this page\r\n"),
1887
1888 // Lastly we get the desired content.
1889 MockRead("HTTP/1.1 200 OK\r\n"),
1890 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1891 MockRead("Content-Length: 13\r\n\r\n"),
1892 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421893 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291894 };
1895
[email protected]5ecc992a42009-11-11 01:41:591896 StaticSocketDataProvider data1(data_reads1, data_writes1);
1897 StaticSocketDataProvider data2(data_reads2, data_writes2);
1898 StaticSocketDataProvider data3(data_reads3, data_writes3);
1899 session_deps.socket_factory.AddSocketDataProvider(&data1);
1900 session_deps.socket_factory.AddSocketDataProvider(&data2);
1901 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:291902
1903 TestCompletionCallback callback1;
1904
[email protected]684970b2009-08-14 04:54:461905 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421906 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291907
1908 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421909 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291910
[email protected]0757e7702009-03-27 04:00:221911 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291912 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221913 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421914 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291915 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421916 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221917 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291918
[email protected]1c773ea12009-04-28 19:58:421919 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291920 EXPECT_FALSE(response == NULL);
1921
1922 // The password prompt info should have been set in response->auth_challenge.
1923 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1924
[email protected]71e4573a2009-05-21 22:03:001925 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291926 EXPECT_EQ(L"", response->auth_challenge->realm);
1927 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1928
1929 TestCompletionCallback callback3;
1930
[email protected]0757e7702009-03-27 04:00:221931 // Enter the wrong password.
1932 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421933 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291934
1935 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421936 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291937
[email protected]0757e7702009-03-27 04:00:221938 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1939 TestCompletionCallback callback4;
1940 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421941 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221942 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421943 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221944 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1945
1946 response = trans->GetResponseInfo();
1947 EXPECT_FALSE(response == NULL);
1948
1949 // The password prompt info should have been set in response->auth_challenge.
1950 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1951
[email protected]71e4573a2009-05-21 22:03:001952 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221953 EXPECT_EQ(L"", response->auth_challenge->realm);
1954 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1955
1956 TestCompletionCallback callback5;
1957
1958 // Now enter the right password.
1959 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:421960 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221961
1962 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421963 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221964
[email protected]385a4672009-03-11 22:21:291965 response = trans->GetResponseInfo();
1966 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1967 EXPECT_EQ(13, response->headers->GetContentLength());
1968}
[email protected]ea9dc9a2009-09-05 00:43:321969#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:291970
[email protected]4ddaf2502008-10-23 18:26:191971// Test reading a server response which has only headers, and no body.
1972// After some maximum number of bytes is consumed, the transaction should
1973// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
1974TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:591975 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401976 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431977 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:191978
[email protected]1c773ea12009-04-28 19:58:421979 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:191980 request.method = "GET";
1981 request.url = GURL("http://www.google.com/");
1982 request.load_flags = 0;
1983
[email protected]b75b7b2f2009-10-06 00:54:531984 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:431985 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:531986 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:191987
1988 MockRead data_reads[] = {
1989 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:431990 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:191991 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:421992 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:191993 };
[email protected]5ecc992a42009-11-11 01:41:591994 StaticSocketDataProvider data(data_reads, NULL);
1995 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:191996
1997 TestCompletionCallback callback;
1998
[email protected]684970b2009-08-14 04:54:461999 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422000 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192001
2002 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422003 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192004
[email protected]1c773ea12009-04-28 19:58:422005 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192006 EXPECT_TRUE(response == NULL);
2007}
[email protected]f4e426b2008-11-05 00:24:492008
2009// Make sure that we don't try to reuse a TCPClientSocket when failing to
2010// establish tunnel.
2011// http://code.google.com/p/chromium/issues/detail?id=3772
2012TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2013 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592014 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012015
[email protected]228ff742009-06-05 01:19:592016 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492017
[email protected]5695b8c2009-09-30 21:36:432018 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492019
[email protected]1c773ea12009-04-28 19:58:422020 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492021 request.method = "GET";
2022 request.url = GURL("https://www.google.com/");
2023 request.load_flags = 0;
2024
2025 // Since we have proxy, should try to establish tunnel.
2026 MockWrite data_writes1[] = {
2027 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452028 "Host: www.google.com\r\n"
2029 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492030 };
2031
[email protected]77848d12008-11-14 00:00:222032 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492033 // connection. Usually a proxy would return 501 (not implemented),
2034 // or 200 (tunnel established).
2035 MockRead data_reads1[] = {
2036 MockRead("HTTP/1.1 404 Not Found\r\n"),
2037 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422038 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492039 };
2040
[email protected]5ecc992a42009-11-11 01:41:592041 StaticSocketDataProvider data1(data_reads1, data_writes1);
2042 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492043
2044 TestCompletionCallback callback1;
2045
[email protected]684970b2009-08-14 04:54:462046 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422047 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492048
2049 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422050 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492051
[email protected]1c773ea12009-04-28 19:58:422052 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082053 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492054
[email protected]b4404c02009-04-10 16:38:522055 // Empty the current queue. This is necessary because idle sockets are
2056 // added to the connection pool asynchronously with a PostTask.
2057 MessageLoop::current()->RunAllPending();
2058
[email protected]f4e426b2008-11-05 00:24:492059 // We now check to make sure the TCPClientSocket was not added back to
2060 // the pool.
[email protected]a937a06d2009-08-19 21:19:242061 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492062 trans.reset();
[email protected]b4404c02009-04-10 16:38:522063 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492064 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242065 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492066}
[email protected]372d34a2008-11-05 21:30:512067
[email protected]1b157c02009-04-21 01:55:402068// Make sure that we recycle a socket after reading all of the response body.
2069TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592070 SessionDependencies session_deps;
2071 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402072
[email protected]5695b8c2009-09-30 21:36:432073 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402074
[email protected]1c773ea12009-04-28 19:58:422075 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402076 request.method = "GET";
2077 request.url = GURL("http://www.google.com/");
2078 request.load_flags = 0;
2079
2080 MockRead data_reads[] = {
2081 // A part of the response body is received with the response headers.
2082 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2083 // The rest of the response body is received in two parts.
2084 MockRead("lo"),
2085 MockRead(" world"),
2086 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422087 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402088 };
2089
[email protected]5ecc992a42009-11-11 01:41:592090 StaticSocketDataProvider data(data_reads, NULL);
2091 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402092
2093 TestCompletionCallback callback;
2094
[email protected]684970b2009-08-14 04:54:462095 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422096 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402097
2098 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422099 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402100
[email protected]1c773ea12009-04-28 19:58:422101 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402102 EXPECT_TRUE(response != NULL);
2103
2104 EXPECT_TRUE(response->headers != NULL);
2105 std::string status_line = response->headers->GetStatusLine();
2106 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2107
[email protected]a937a06d2009-08-19 21:19:242108 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402109
2110 std::string response_data;
2111 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422112 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402113 EXPECT_EQ("hello world", response_data);
2114
2115 // Empty the current queue. This is necessary because idle sockets are
2116 // added to the connection pool asynchronously with a PostTask.
2117 MessageLoop::current()->RunAllPending();
2118
2119 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242120 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402121}
2122
[email protected]b4404c02009-04-10 16:38:522123// Make sure that we recycle a socket after a zero-length response.
2124// http://crbug.com/9880
2125TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592126 SessionDependencies session_deps;
2127 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522128
[email protected]5695b8c2009-09-30 21:36:432129 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522130
[email protected]1c773ea12009-04-28 19:58:422131 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522132 request.method = "GET";
2133 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2134 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2135 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2136 "rt=prt.2642,ol.2649,xjs.2951");
2137 request.load_flags = 0;
2138
2139 MockRead data_reads[] = {
2140 MockRead("HTTP/1.1 204 No Content\r\n"
2141 "Content-Length: 0\r\n"
2142 "Content-Type: text/html\r\n\r\n"),
2143 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422144 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522145 };
2146
[email protected]5ecc992a42009-11-11 01:41:592147 StaticSocketDataProvider data(data_reads, NULL);
2148 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522149
2150 TestCompletionCallback callback;
2151
[email protected]684970b2009-08-14 04:54:462152 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422153 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522154
2155 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422156 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522157
[email protected]1c773ea12009-04-28 19:58:422158 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522159 EXPECT_TRUE(response != NULL);
2160
2161 EXPECT_TRUE(response->headers != NULL);
2162 std::string status_line = response->headers->GetStatusLine();
2163 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2164
[email protected]a937a06d2009-08-19 21:19:242165 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522166
2167 std::string response_data;
2168 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422169 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522170 EXPECT_EQ("", response_data);
2171
2172 // Empty the current queue. This is necessary because idle sockets are
2173 // added to the connection pool asynchronously with a PostTask.
2174 MessageLoop::current()->RunAllPending();
2175
2176 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242177 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522178}
2179
[email protected]372d34a2008-11-05 21:30:512180TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422181 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512182 // Transaction 1: a GET request that succeeds. The socket is recycled
2183 // after use.
2184 request[0].method = "GET";
2185 request[0].url = GURL("http://www.google.com/");
2186 request[0].load_flags = 0;
2187 // Transaction 2: a POST request. Reuses the socket kept alive from
2188 // transaction 1. The first attempts fails when writing the POST data.
2189 // This causes the transaction to retry with a new socket. The second
2190 // attempt succeeds.
2191 request[1].method = "POST";
2192 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422193 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512194 request[1].upload_data->AppendBytes("foo", 3);
2195 request[1].load_flags = 0;
2196
[email protected]228ff742009-06-05 01:19:592197 SessionDependencies session_deps;
2198 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512199
2200 // The first socket is used for transaction 1 and the first attempt of
2201 // transaction 2.
2202
2203 // The response of transaction 1.
2204 MockRead data_reads1[] = {
2205 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2206 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422207 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512208 };
2209 // The mock write results of transaction 1 and the first attempt of
2210 // transaction 2.
2211 MockWrite data_writes1[] = {
2212 MockWrite(false, 64), // GET
2213 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422214 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512215 };
[email protected]5ecc992a42009-11-11 01:41:592216 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:512217
2218 // The second socket is used for the second attempt of transaction 2.
2219
2220 // The response of transaction 2.
2221 MockRead data_reads2[] = {
2222 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2223 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422224 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512225 };
2226 // The mock write results of the second attempt of transaction 2.
2227 MockWrite data_writes2[] = {
2228 MockWrite(false, 93), // POST
2229 MockWrite(false, 3), // POST data
2230 };
[email protected]5ecc992a42009-11-11 01:41:592231 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:512232
[email protected]5ecc992a42009-11-11 01:41:592233 session_deps.socket_factory.AddSocketDataProvider(&data1);
2234 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512235
2236 const char* kExpectedResponseData[] = {
2237 "hello world", "welcome"
2238 };
2239
2240 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422241 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432242 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512243
2244 TestCompletionCallback callback;
2245
[email protected]684970b2009-08-14 04:54:462246 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422247 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512248
2249 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422250 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512251
[email protected]1c773ea12009-04-28 19:58:422252 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512253 EXPECT_TRUE(response != NULL);
2254
2255 EXPECT_TRUE(response->headers != NULL);
2256 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2257
2258 std::string response_data;
2259 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422260 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512261 EXPECT_EQ(kExpectedResponseData[i], response_data);
2262 }
2263}
[email protected]f9ee6b52008-11-08 06:46:232264
2265// Test the request-challenge-retry sequence for basic auth when there is
2266// an identity in the URL. The request should be sent as normal, but when
2267// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322268TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592269 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402270 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432271 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232272
[email protected]1c773ea12009-04-28 19:58:422273 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232274 request.method = "GET";
2275 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292276 request.url = GURL("http://foo:b@[email protected]/");
2277
2278 // The password contains an escaped character -- for this test to pass it
2279 // will need to be unescaped by HttpNetworkTransaction.
2280 EXPECT_EQ("b%40r", request.url.password());
2281
[email protected]ea9dc9a2009-09-05 00:43:322282 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232283
2284 MockWrite data_writes1[] = {
2285 MockWrite("GET / HTTP/1.1\r\n"
2286 "Host: www.google.com\r\n"
2287 "Connection: keep-alive\r\n\r\n"),
2288 };
2289
2290 MockRead data_reads1[] = {
2291 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2292 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2293 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422294 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232295 };
2296
2297 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322298 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232299 MockWrite data_writes2[] = {
2300 MockWrite("GET / HTTP/1.1\r\n"
2301 "Host: www.google.com\r\n"
2302 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292303 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232304 };
2305
2306 MockRead data_reads2[] = {
2307 MockRead("HTTP/1.0 200 OK\r\n"),
2308 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422309 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232310 };
2311
[email protected]5ecc992a42009-11-11 01:41:592312 StaticSocketDataProvider data1(data_reads1, data_writes1);
2313 StaticSocketDataProvider data2(data_reads2, data_writes2);
2314 session_deps.socket_factory.AddSocketDataProvider(&data1);
2315 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232316
2317 TestCompletionCallback callback1;
2318
[email protected]684970b2009-08-14 04:54:462319 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422320 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232321
2322 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422323 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232324
[email protected]0757e7702009-03-27 04:00:222325 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2326 TestCompletionCallback callback2;
2327 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422328 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222329 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422330 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222331 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2332
[email protected]1c773ea12009-04-28 19:58:422333 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232334 EXPECT_FALSE(response == NULL);
2335
2336 // There is no challenge info, since the identity in URL worked.
2337 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2338
2339 EXPECT_EQ(100, response->headers->GetContentLength());
2340
2341 // Empty the current queue.
2342 MessageLoop::current()->RunAllPending();
2343}
2344
[email protected]ea9dc9a2009-09-05 00:43:322345// Test the request-challenge-retry sequence for basic auth when there is
2346// an incorrect identity in the URL. The identity from the URL should be used
2347// only once.
2348TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2349 SessionDependencies session_deps;
2350 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432351 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322352
2353 HttpRequestInfo request;
2354 request.method = "GET";
2355 // Note: the URL has a username:password in it. The password "baz" is
2356 // wrong (should be "bar").
2357 request.url = GURL("http://foo:[email protected]/");
2358
2359 request.load_flags = LOAD_NORMAL;
2360
2361 MockWrite data_writes1[] = {
2362 MockWrite("GET / HTTP/1.1\r\n"
2363 "Host: www.google.com\r\n"
2364 "Connection: keep-alive\r\n\r\n"),
2365 };
2366
2367 MockRead data_reads1[] = {
2368 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2369 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2370 MockRead("Content-Length: 10\r\n\r\n"),
2371 MockRead(false, ERR_FAILED),
2372 };
2373
2374 // After the challenge above, the transaction will be restarted using the
2375 // identity from the url (foo, baz) to answer the challenge.
2376 MockWrite data_writes2[] = {
2377 MockWrite("GET / HTTP/1.1\r\n"
2378 "Host: www.google.com\r\n"
2379 "Connection: keep-alive\r\n"
2380 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2381 };
2382
2383 MockRead data_reads2[] = {
2384 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2385 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2386 MockRead("Content-Length: 10\r\n\r\n"),
2387 MockRead(false, ERR_FAILED),
2388 };
2389
2390 // After the challenge above, the transaction will be restarted using the
2391 // identity supplied by the user (foo, bar) to answer the challenge.
2392 MockWrite data_writes3[] = {
2393 MockWrite("GET / HTTP/1.1\r\n"
2394 "Host: www.google.com\r\n"
2395 "Connection: keep-alive\r\n"
2396 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2397 };
2398
2399 MockRead data_reads3[] = {
2400 MockRead("HTTP/1.0 200 OK\r\n"),
2401 MockRead("Content-Length: 100\r\n\r\n"),
2402 MockRead(false, OK),
2403 };
2404
[email protected]5ecc992a42009-11-11 01:41:592405 StaticSocketDataProvider data1(data_reads1, data_writes1);
2406 StaticSocketDataProvider data2(data_reads2, data_writes2);
2407 StaticSocketDataProvider data3(data_reads3, data_writes3);
2408 session_deps.socket_factory.AddSocketDataProvider(&data1);
2409 session_deps.socket_factory.AddSocketDataProvider(&data2);
2410 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322411
2412 TestCompletionCallback callback1;
2413
2414 int rv = trans->Start(&request, &callback1, NULL);
2415 EXPECT_EQ(ERR_IO_PENDING, rv);
2416
2417 rv = callback1.WaitForResult();
2418 EXPECT_EQ(OK, rv);
2419
2420 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2421 TestCompletionCallback callback2;
2422 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2423 EXPECT_EQ(ERR_IO_PENDING, rv);
2424 rv = callback2.WaitForResult();
2425 EXPECT_EQ(OK, rv);
2426 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2427
2428 const HttpResponseInfo* response = trans->GetResponseInfo();
2429 EXPECT_FALSE(response == NULL);
2430 // The password prompt info should have been set in response->auth_challenge.
2431 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2432
2433 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2434 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2435 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2436
2437 TestCompletionCallback callback3;
2438 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2439 EXPECT_EQ(ERR_IO_PENDING, rv);
2440 rv = callback3.WaitForResult();
2441 EXPECT_EQ(OK, rv);
2442 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2443
2444 response = trans->GetResponseInfo();
2445 EXPECT_FALSE(response == NULL);
2446
2447 // There is no challenge info, since the identity worked.
2448 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2449
2450 EXPECT_EQ(100, response->headers->GetContentLength());
2451
2452 // Empty the current queue.
2453 MessageLoop::current()->RunAllPending();
2454}
2455
[email protected]f9ee6b52008-11-08 06:46:232456// Test that previously tried username/passwords for a realm get re-used.
2457TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592458 SessionDependencies session_deps;
2459 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232460
2461 // Transaction 1: authenticate (foo, bar) on MyRealm1
2462 {
[email protected]5695b8c2009-09-30 21:36:432463 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232464
[email protected]1c773ea12009-04-28 19:58:422465 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232466 request.method = "GET";
2467 request.url = GURL("http://www.google.com/x/y/z");
2468 request.load_flags = 0;
2469
2470 MockWrite data_writes1[] = {
2471 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2472 "Host: www.google.com\r\n"
2473 "Connection: keep-alive\r\n\r\n"),
2474 };
2475
2476 MockRead data_reads1[] = {
2477 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2478 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2479 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422480 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232481 };
2482
2483 // Resend with authorization (username=foo, password=bar)
2484 MockWrite data_writes2[] = {
2485 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2486 "Host: www.google.com\r\n"
2487 "Connection: keep-alive\r\n"
2488 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2489 };
2490
2491 // Sever accepts the authorization.
2492 MockRead data_reads2[] = {
2493 MockRead("HTTP/1.0 200 OK\r\n"),
2494 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422495 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232496 };
2497
[email protected]5ecc992a42009-11-11 01:41:592498 StaticSocketDataProvider data1(data_reads1, data_writes1);
2499 StaticSocketDataProvider data2(data_reads2, data_writes2);
2500 session_deps.socket_factory.AddSocketDataProvider(&data1);
2501 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232502
2503 TestCompletionCallback callback1;
2504
[email protected]684970b2009-08-14 04:54:462505 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422506 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232507
2508 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422509 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232510
[email protected]1c773ea12009-04-28 19:58:422511 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232512 EXPECT_FALSE(response == NULL);
2513
2514 // The password prompt info should have been set in
2515 // response->auth_challenge.
2516 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2517
[email protected]71e4573a2009-05-21 22:03:002518 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232519 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2520 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2521
2522 TestCompletionCallback callback2;
2523
2524 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422525 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232526
2527 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422528 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232529
2530 response = trans->GetResponseInfo();
2531 EXPECT_FALSE(response == NULL);
2532 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2533 EXPECT_EQ(100, response->headers->GetContentLength());
2534 }
2535
2536 // ------------------------------------------------------------------------
2537
2538 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2539 {
[email protected]5695b8c2009-09-30 21:36:432540 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232541
[email protected]1c773ea12009-04-28 19:58:422542 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232543 request.method = "GET";
2544 // Note that Transaction 1 was at /x/y/z, so this is in the same
2545 // protection space as MyRealm1.
2546 request.url = GURL("http://www.google.com/x/y/a/b");
2547 request.load_flags = 0;
2548
2549 MockWrite data_writes1[] = {
2550 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2551 "Host: www.google.com\r\n"
2552 "Connection: keep-alive\r\n"
2553 // Send preemptive authorization for MyRealm1
2554 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2555 };
2556
2557 // The server didn't like the preemptive authorization, and
2558 // challenges us for a different realm (MyRealm2).
2559 MockRead data_reads1[] = {
2560 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2561 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2562 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422563 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232564 };
2565
2566 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2567 MockWrite data_writes2[] = {
2568 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2569 "Host: www.google.com\r\n"
2570 "Connection: keep-alive\r\n"
2571 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2572 };
2573
2574 // Sever accepts the authorization.
2575 MockRead data_reads2[] = {
2576 MockRead("HTTP/1.0 200 OK\r\n"),
2577 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422578 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232579 };
2580
[email protected]5ecc992a42009-11-11 01:41:592581 StaticSocketDataProvider data1(data_reads1, data_writes1);
2582 StaticSocketDataProvider data2(data_reads2, data_writes2);
2583 session_deps.socket_factory.AddSocketDataProvider(&data1);
2584 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232585
2586 TestCompletionCallback callback1;
2587
[email protected]684970b2009-08-14 04:54:462588 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422589 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232590
2591 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422592 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232593
[email protected]1c773ea12009-04-28 19:58:422594 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232595 EXPECT_FALSE(response == NULL);
2596
2597 // The password prompt info should have been set in
2598 // response->auth_challenge.
2599 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2600
[email protected]71e4573a2009-05-21 22:03:002601 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232602 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2603 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2604
2605 TestCompletionCallback callback2;
2606
2607 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422608 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232609
2610 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422611 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232612
2613 response = trans->GetResponseInfo();
2614 EXPECT_FALSE(response == NULL);
2615 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2616 EXPECT_EQ(100, response->headers->GetContentLength());
2617 }
2618
2619 // ------------------------------------------------------------------------
2620
2621 // Transaction 3: Resend a request in MyRealm's protection space --
2622 // succeed with preemptive authorization.
2623 {
[email protected]5695b8c2009-09-30 21:36:432624 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232625
[email protected]1c773ea12009-04-28 19:58:422626 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232627 request.method = "GET";
2628 request.url = GURL("http://www.google.com/x/y/z2");
2629 request.load_flags = 0;
2630
2631 MockWrite data_writes1[] = {
2632 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2633 "Host: www.google.com\r\n"
2634 "Connection: keep-alive\r\n"
2635 // The authorization for MyRealm1 gets sent preemptively
2636 // (since the url is in the same protection space)
2637 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2638 };
2639
2640 // Sever accepts the preemptive authorization
2641 MockRead data_reads1[] = {
2642 MockRead("HTTP/1.0 200 OK\r\n"),
2643 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422644 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232645 };
2646
[email protected]5ecc992a42009-11-11 01:41:592647 StaticSocketDataProvider data1(data_reads1, data_writes1);
2648 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232649
2650 TestCompletionCallback callback1;
2651
[email protected]684970b2009-08-14 04:54:462652 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422653 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232654
2655 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422656 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232657
[email protected]1c773ea12009-04-28 19:58:422658 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232659 EXPECT_FALSE(response == NULL);
2660
2661 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2662 EXPECT_EQ(100, response->headers->GetContentLength());
2663 }
2664
2665 // ------------------------------------------------------------------------
2666
2667 // Transaction 4: request another URL in MyRealm (however the
2668 // url is not known to belong to the protection space, so no pre-auth).
2669 {
[email protected]5695b8c2009-09-30 21:36:432670 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232671
[email protected]1c773ea12009-04-28 19:58:422672 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232673 request.method = "GET";
2674 request.url = GURL("http://www.google.com/x/1");
2675 request.load_flags = 0;
2676
2677 MockWrite data_writes1[] = {
2678 MockWrite("GET /x/1 HTTP/1.1\r\n"
2679 "Host: www.google.com\r\n"
2680 "Connection: keep-alive\r\n\r\n"),
2681 };
2682
2683 MockRead data_reads1[] = {
2684 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2685 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2686 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422687 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232688 };
2689
2690 // Resend with authorization from MyRealm's cache.
2691 MockWrite data_writes2[] = {
2692 MockWrite("GET /x/1 HTTP/1.1\r\n"
2693 "Host: www.google.com\r\n"
2694 "Connection: keep-alive\r\n"
2695 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2696 };
2697
2698 // Sever accepts the authorization.
2699 MockRead data_reads2[] = {
2700 MockRead("HTTP/1.0 200 OK\r\n"),
2701 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422702 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232703 };
2704
[email protected]5ecc992a42009-11-11 01:41:592705 StaticSocketDataProvider data1(data_reads1, data_writes1);
2706 StaticSocketDataProvider data2(data_reads2, data_writes2);
2707 session_deps.socket_factory.AddSocketDataProvider(&data1);
2708 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232709
2710 TestCompletionCallback callback1;
2711
[email protected]684970b2009-08-14 04:54:462712 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422713 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232714
2715 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422716 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232717
[email protected]0757e7702009-03-27 04:00:222718 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2719 TestCompletionCallback callback2;
2720 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422721 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222722 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422723 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222724 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2725
[email protected]1c773ea12009-04-28 19:58:422726 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232727 EXPECT_FALSE(response == NULL);
2728 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2729 EXPECT_EQ(100, response->headers->GetContentLength());
2730 }
2731
2732 // ------------------------------------------------------------------------
2733
2734 // Transaction 5: request a URL in MyRealm, but the server rejects the
2735 // cached identity. Should invalidate and re-prompt.
2736 {
[email protected]5695b8c2009-09-30 21:36:432737 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232738
[email protected]1c773ea12009-04-28 19:58:422739 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232740 request.method = "GET";
2741 request.url = GURL("http://www.google.com/p/q/t");
2742 request.load_flags = 0;
2743
2744 MockWrite data_writes1[] = {
2745 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2746 "Host: www.google.com\r\n"
2747 "Connection: keep-alive\r\n\r\n"),
2748 };
2749
2750 MockRead data_reads1[] = {
2751 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2752 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2753 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422754 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232755 };
2756
2757 // Resend with authorization from cache for MyRealm.
2758 MockWrite data_writes2[] = {
2759 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2760 "Host: www.google.com\r\n"
2761 "Connection: keep-alive\r\n"
2762 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2763 };
2764
2765 // Sever rejects the authorization.
2766 MockRead data_reads2[] = {
2767 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2768 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2769 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422770 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232771 };
2772
2773 // At this point we should prompt for new credentials for MyRealm.
2774 // Restart with username=foo3, password=foo4.
2775 MockWrite data_writes3[] = {
2776 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2777 "Host: www.google.com\r\n"
2778 "Connection: keep-alive\r\n"
2779 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2780 };
2781
2782 // Sever accepts the authorization.
2783 MockRead data_reads3[] = {
2784 MockRead("HTTP/1.0 200 OK\r\n"),
2785 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422786 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232787 };
2788
[email protected]5ecc992a42009-11-11 01:41:592789 StaticSocketDataProvider data1(data_reads1, data_writes1);
2790 StaticSocketDataProvider data2(data_reads2, data_writes2);
2791 StaticSocketDataProvider data3(data_reads3, data_writes3);
2792 session_deps.socket_factory.AddSocketDataProvider(&data1);
2793 session_deps.socket_factory.AddSocketDataProvider(&data2);
2794 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232795
2796 TestCompletionCallback callback1;
2797
[email protected]684970b2009-08-14 04:54:462798 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422799 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232800
2801 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422802 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232803
[email protected]0757e7702009-03-27 04:00:222804 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2805 TestCompletionCallback callback2;
2806 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422807 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222808 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422809 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222810 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2811
[email protected]1c773ea12009-04-28 19:58:422812 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232813 EXPECT_FALSE(response == NULL);
2814
2815 // The password prompt info should have been set in
2816 // response->auth_challenge.
2817 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2818
[email protected]71e4573a2009-05-21 22:03:002819 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232820 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2821 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2822
[email protected]0757e7702009-03-27 04:00:222823 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232824
[email protected]0757e7702009-03-27 04:00:222825 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422826 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232827
[email protected]0757e7702009-03-27 04:00:222828 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422829 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232830
2831 response = trans->GetResponseInfo();
2832 EXPECT_FALSE(response == NULL);
2833 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2834 EXPECT_EQ(100, response->headers->GetContentLength());
2835 }
2836}
[email protected]89ceba9a2009-03-21 03:46:062837
2838// Test the ResetStateForRestart() private method.
2839TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2840 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592841 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402842 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432843 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062844
2845 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062846 trans->read_buf_ = new IOBuffer(15);
2847 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572848 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062849
2850 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:142851 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:572852 response->auth_challenge = new AuthChallengeInfo();
2853 response->ssl_info.cert_status = -15;
2854 response->response_time = base::Time::Now();
2855 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062856
2857 { // Setup state for response_.vary_data
2858 HttpRequestInfo request;
2859 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2860 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:572861 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]89ceba9a2009-03-21 03:46:062862 request.extra_headers = "Foo: 1\nbar: 23";
[email protected]0877e3d2009-10-17 22:29:572863 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:062864 }
2865
2866 // Cause the above state to be reset.
2867 trans->ResetStateForRestart();
2868
2869 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:072870 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:062871 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:572872 EXPECT_EQ(0U, trans->request_headers_.size());
2873 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2874 EXPECT_TRUE(response->headers.get() == NULL);
2875 EXPECT_EQ(false, response->was_cached);
2876 EXPECT_EQ(0, response->ssl_info.cert_status);
2877 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:062878}
2879
[email protected]bacff652009-03-31 17:50:332880// Test HTTPS connections to a site with a bad certificate
2881TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592882 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402883 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432884 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332885
2886 HttpRequestInfo request;
2887 request.method = "GET";
2888 request.url = GURL("https://www.google.com/");
2889 request.load_flags = 0;
2890
2891 MockWrite data_writes[] = {
2892 MockWrite("GET / HTTP/1.1\r\n"
2893 "Host: www.google.com\r\n"
2894 "Connection: keep-alive\r\n\r\n"),
2895 };
2896
2897 MockRead data_reads[] = {
2898 MockRead("HTTP/1.0 200 OK\r\n"),
2899 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2900 MockRead("Content-Length: 100\r\n\r\n"),
2901 MockRead(false, OK),
2902 };
2903
[email protected]5ecc992a42009-11-11 01:41:592904 StaticSocketDataProvider ssl_bad_certificate;
2905 StaticSocketDataProvider data(data_reads, data_writes);
2906 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2907 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:332908
[email protected]5ecc992a42009-11-11 01:41:592909 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2910 session_deps.socket_factory.AddSocketDataProvider(&data);
2911 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2912 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:332913
2914 TestCompletionCallback callback;
2915
[email protected]684970b2009-08-14 04:54:462916 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332917 EXPECT_EQ(ERR_IO_PENDING, rv);
2918
2919 rv = callback.WaitForResult();
2920 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2921
2922 rv = trans->RestartIgnoringLastError(&callback);
2923 EXPECT_EQ(ERR_IO_PENDING, rv);
2924
2925 rv = callback.WaitForResult();
2926 EXPECT_EQ(OK, rv);
2927
2928 const HttpResponseInfo* response = trans->GetResponseInfo();
2929
2930 EXPECT_FALSE(response == NULL);
2931 EXPECT_EQ(100, response->headers->GetContentLength());
2932}
2933
2934// Test HTTPS connections to a site with a bad certificate, going through a
2935// proxy
2936TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592937 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332938
2939 HttpRequestInfo request;
2940 request.method = "GET";
2941 request.url = GURL("https://www.google.com/");
2942 request.load_flags = 0;
2943
2944 MockWrite proxy_writes[] = {
2945 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452946 "Host: www.google.com\r\n"
2947 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332948 };
2949
2950 MockRead proxy_reads[] = {
2951 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422952 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:332953 };
2954
2955 MockWrite data_writes[] = {
2956 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452957 "Host: www.google.com\r\n"
2958 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332959 MockWrite("GET / HTTP/1.1\r\n"
2960 "Host: www.google.com\r\n"
2961 "Connection: keep-alive\r\n\r\n"),
2962 };
2963
2964 MockRead data_reads[] = {
2965 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
2966 MockRead("HTTP/1.0 200 OK\r\n"),
2967 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2968 MockRead("Content-Length: 100\r\n\r\n"),
2969 MockRead(false, OK),
2970 };
2971
[email protected]5ecc992a42009-11-11 01:41:592972 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
2973 StaticSocketDataProvider data(data_reads, data_writes);
2974 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2975 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:332976
[email protected]5ecc992a42009-11-11 01:41:592977 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2978 session_deps.socket_factory.AddSocketDataProvider(&data);
2979 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2980 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:332981
2982 TestCompletionCallback callback;
2983
2984 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:592985 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:332986
[email protected]d207a5f2009-06-04 05:28:402987 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432988 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332989
[email protected]684970b2009-08-14 04:54:462990 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332991 EXPECT_EQ(ERR_IO_PENDING, rv);
2992
2993 rv = callback.WaitForResult();
2994 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2995
2996 rv = trans->RestartIgnoringLastError(&callback);
2997 EXPECT_EQ(ERR_IO_PENDING, rv);
2998
2999 rv = callback.WaitForResult();
3000 EXPECT_EQ(OK, rv);
3001
3002 const HttpResponseInfo* response = trans->GetResponseInfo();
3003
3004 EXPECT_FALSE(response == NULL);
3005 EXPECT_EQ(100, response->headers->GetContentLength());
3006 }
3007}
3008
[email protected]1c773ea12009-04-28 19:58:423009TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593010 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403011 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433012 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423013
3014 HttpRequestInfo request;
3015 request.method = "GET";
3016 request.url = GURL("http://www.google.com/");
3017 request.user_agent = "Chromium Ultra Awesome X Edition";
3018
3019 MockWrite data_writes[] = {
3020 MockWrite("GET / HTTP/1.1\r\n"
3021 "Host: www.google.com\r\n"
3022 "Connection: keep-alive\r\n"
3023 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3024 };
3025
3026 // Lastly, the server responds with the actual content.
3027 MockRead data_reads[] = {
3028 MockRead("HTTP/1.0 200 OK\r\n"),
3029 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3030 MockRead("Content-Length: 100\r\n\r\n"),
3031 MockRead(false, OK),
3032 };
3033
[email protected]5ecc992a42009-11-11 01:41:593034 StaticSocketDataProvider data(data_reads, data_writes);
3035 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423036
3037 TestCompletionCallback callback;
3038
[email protected]684970b2009-08-14 04:54:463039 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423040 EXPECT_EQ(ERR_IO_PENDING, rv);
3041
3042 rv = callback.WaitForResult();
3043 EXPECT_EQ(OK, rv);
3044}
3045
3046TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593047 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403048 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433049 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423050
3051 HttpRequestInfo request;
3052 request.method = "GET";
3053 request.url = GURL("http://www.google.com/");
3054 request.load_flags = 0;
3055 request.referrer = GURL("http://the.previous.site.com/");
3056
3057 MockWrite data_writes[] = {
3058 MockWrite("GET / HTTP/1.1\r\n"
3059 "Host: www.google.com\r\n"
3060 "Connection: keep-alive\r\n"
3061 "Referer: http://the.previous.site.com/\r\n\r\n"),
3062 };
3063
3064 // Lastly, the server responds with the actual content.
3065 MockRead data_reads[] = {
3066 MockRead("HTTP/1.0 200 OK\r\n"),
3067 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3068 MockRead("Content-Length: 100\r\n\r\n"),
3069 MockRead(false, OK),
3070 };
3071
[email protected]5ecc992a42009-11-11 01:41:593072 StaticSocketDataProvider data(data_reads, data_writes);
3073 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423074
3075 TestCompletionCallback callback;
3076
[email protected]684970b2009-08-14 04:54:463077 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423078 EXPECT_EQ(ERR_IO_PENDING, rv);
3079
3080 rv = callback.WaitForResult();
3081 EXPECT_EQ(OK, rv);
3082}
3083
3084TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593085 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403086 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433087 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423088
3089 HttpRequestInfo request;
3090 request.method = "POST";
3091 request.url = GURL("http://www.google.com/");
3092
3093 MockWrite data_writes[] = {
3094 MockWrite("POST / HTTP/1.1\r\n"
3095 "Host: www.google.com\r\n"
3096 "Connection: keep-alive\r\n"
3097 "Content-Length: 0\r\n\r\n"),
3098 };
3099
3100 // Lastly, the server responds with the actual content.
3101 MockRead data_reads[] = {
3102 MockRead("HTTP/1.0 200 OK\r\n"),
3103 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3104 MockRead("Content-Length: 100\r\n\r\n"),
3105 MockRead(false, OK),
3106 };
3107
[email protected]5ecc992a42009-11-11 01:41:593108 StaticSocketDataProvider data(data_reads, data_writes);
3109 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423110
3111 TestCompletionCallback callback;
3112
[email protected]684970b2009-08-14 04:54:463113 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423114 EXPECT_EQ(ERR_IO_PENDING, rv);
3115
3116 rv = callback.WaitForResult();
3117 EXPECT_EQ(OK, rv);
3118}
3119
3120TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593121 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403122 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433123 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423124
3125 HttpRequestInfo request;
3126 request.method = "PUT";
3127 request.url = GURL("http://www.google.com/");
3128
3129 MockWrite data_writes[] = {
3130 MockWrite("PUT / HTTP/1.1\r\n"
3131 "Host: www.google.com\r\n"
3132 "Connection: keep-alive\r\n"
3133 "Content-Length: 0\r\n\r\n"),
3134 };
3135
3136 // Lastly, the server responds with the actual content.
3137 MockRead data_reads[] = {
3138 MockRead("HTTP/1.0 200 OK\r\n"),
3139 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3140 MockRead("Content-Length: 100\r\n\r\n"),
3141 MockRead(false, OK),
3142 };
3143
[email protected]5ecc992a42009-11-11 01:41:593144 StaticSocketDataProvider data(data_reads, data_writes);
3145 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423146
3147 TestCompletionCallback callback;
3148
[email protected]684970b2009-08-14 04:54:463149 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423150 EXPECT_EQ(ERR_IO_PENDING, rv);
3151
3152 rv = callback.WaitForResult();
3153 EXPECT_EQ(OK, rv);
3154}
3155
3156TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593157 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403158 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433159 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423160
3161 HttpRequestInfo request;
3162 request.method = "HEAD";
3163 request.url = GURL("http://www.google.com/");
3164
3165 MockWrite data_writes[] = {
3166 MockWrite("HEAD / HTTP/1.1\r\n"
3167 "Host: www.google.com\r\n"
3168 "Connection: keep-alive\r\n"
3169 "Content-Length: 0\r\n\r\n"),
3170 };
3171
3172 // Lastly, the server responds with the actual content.
3173 MockRead data_reads[] = {
3174 MockRead("HTTP/1.0 200 OK\r\n"),
3175 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3176 MockRead("Content-Length: 100\r\n\r\n"),
3177 MockRead(false, OK),
3178 };
3179
[email protected]5ecc992a42009-11-11 01:41:593180 StaticSocketDataProvider data(data_reads, data_writes);
3181 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423182
3183 TestCompletionCallback callback;
3184
[email protected]684970b2009-08-14 04:54:463185 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423186 EXPECT_EQ(ERR_IO_PENDING, rv);
3187
3188 rv = callback.WaitForResult();
3189 EXPECT_EQ(OK, rv);
3190}
3191
3192TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593193 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403194 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433195 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423196
3197 HttpRequestInfo request;
3198 request.method = "GET";
3199 request.url = GURL("http://www.google.com/");
3200 request.load_flags = LOAD_BYPASS_CACHE;
3201
3202 MockWrite data_writes[] = {
3203 MockWrite("GET / HTTP/1.1\r\n"
3204 "Host: www.google.com\r\n"
3205 "Connection: keep-alive\r\n"
3206 "Pragma: no-cache\r\n"
3207 "Cache-Control: no-cache\r\n\r\n"),
3208 };
3209
3210 // Lastly, the server responds with the actual content.
3211 MockRead data_reads[] = {
3212 MockRead("HTTP/1.0 200 OK\r\n"),
3213 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3214 MockRead("Content-Length: 100\r\n\r\n"),
3215 MockRead(false, OK),
3216 };
3217
[email protected]5ecc992a42009-11-11 01:41:593218 StaticSocketDataProvider data(data_reads, data_writes);
3219 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423220
3221 TestCompletionCallback callback;
3222
[email protected]684970b2009-08-14 04:54:463223 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423224 EXPECT_EQ(ERR_IO_PENDING, rv);
3225
3226 rv = callback.WaitForResult();
3227 EXPECT_EQ(OK, rv);
3228}
3229
3230TEST_F(HttpNetworkTransactionTest,
3231 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593232 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403233 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433234 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423235
3236 HttpRequestInfo request;
3237 request.method = "GET";
3238 request.url = GURL("http://www.google.com/");
3239 request.load_flags = LOAD_VALIDATE_CACHE;
3240
3241 MockWrite data_writes[] = {
3242 MockWrite("GET / HTTP/1.1\r\n"
3243 "Host: www.google.com\r\n"
3244 "Connection: keep-alive\r\n"
3245 "Cache-Control: max-age=0\r\n\r\n"),
3246 };
3247
3248 // Lastly, the server responds with the actual content.
3249 MockRead data_reads[] = {
3250 MockRead("HTTP/1.0 200 OK\r\n"),
3251 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3252 MockRead("Content-Length: 100\r\n\r\n"),
3253 MockRead(false, OK),
3254 };
3255
[email protected]5ecc992a42009-11-11 01:41:593256 StaticSocketDataProvider data(data_reads, data_writes);
3257 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423258
3259 TestCompletionCallback callback;
3260
[email protected]684970b2009-08-14 04:54:463261 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423262 EXPECT_EQ(ERR_IO_PENDING, rv);
3263
3264 rv = callback.WaitForResult();
3265 EXPECT_EQ(OK, rv);
3266}
3267
3268TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593269 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403270 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433271 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423272
3273 HttpRequestInfo request;
3274 request.method = "GET";
3275 request.url = GURL("http://www.google.com/");
3276 request.extra_headers = "FooHeader: Bar\r\n";
3277
3278 MockWrite data_writes[] = {
3279 MockWrite("GET / HTTP/1.1\r\n"
3280 "Host: www.google.com\r\n"
3281 "Connection: keep-alive\r\n"
3282 "FooHeader: Bar\r\n\r\n"),
3283 };
3284
3285 // Lastly, the server responds with the actual content.
3286 MockRead data_reads[] = {
3287 MockRead("HTTP/1.0 200 OK\r\n"),
3288 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3289 MockRead("Content-Length: 100\r\n\r\n"),
3290 MockRead(false, OK),
3291 };
3292
[email protected]5ecc992a42009-11-11 01:41:593293 StaticSocketDataProvider data(data_reads, data_writes);
3294 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423295
3296 TestCompletionCallback callback;
3297
[email protected]684970b2009-08-14 04:54:463298 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423299 EXPECT_EQ(ERR_IO_PENDING, rv);
3300
3301 rv = callback.WaitForResult();
3302 EXPECT_EQ(OK, rv);
3303}
3304
[email protected]3cd17242009-06-23 02:59:023305TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093306 SessionDependencies session_deps(
3307 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023308
3309 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433310 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023311
3312 HttpRequestInfo request;
3313 request.method = "GET";
3314 request.url = GURL("http://www.google.com/");
3315 request.load_flags = 0;
3316
3317 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3318 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3319
3320 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353321 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023322 MockWrite("GET / HTTP/1.1\r\n"
3323 "Host: www.google.com\r\n"
3324 "Connection: keep-alive\r\n\r\n")
3325 };
3326
3327 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593328 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023329 MockRead("HTTP/1.0 200 OK\r\n"),
3330 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3331 MockRead("Payload"),
3332 MockRead(false, OK)
3333 };
3334
[email protected]5ecc992a42009-11-11 01:41:593335 StaticSocketDataProvider data(data_reads, data_writes);
3336 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023337
3338 TestCompletionCallback callback;
3339
[email protected]684970b2009-08-14 04:54:463340 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023341 EXPECT_EQ(ERR_IO_PENDING, rv);
3342
3343 rv = callback.WaitForResult();
3344 EXPECT_EQ(OK, rv);
3345
3346 const HttpResponseInfo* response = trans->GetResponseInfo();
3347 EXPECT_FALSE(response == NULL);
3348
3349 std::string response_text;
3350 rv = ReadTransaction(trans.get(), &response_text);
3351 EXPECT_EQ(OK, rv);
3352 EXPECT_EQ("Payload", response_text);
3353}
3354
3355TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093356 SessionDependencies session_deps(
3357 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023358
3359 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433360 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023361
3362 HttpRequestInfo request;
3363 request.method = "GET";
3364 request.url = GURL("https://www.google.com/");
3365 request.load_flags = 0;
3366
3367 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3368 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3369
3370 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353371 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3372 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023373 MockWrite("GET / HTTP/1.1\r\n"
3374 "Host: www.google.com\r\n"
3375 "Connection: keep-alive\r\n\r\n")
3376 };
3377
3378 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353379 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3380 arraysize(read_buffer)),
3381 MockRead("HTTP/1.0 200 OK\r\n"),
3382 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3383 MockRead("Payload"),
3384 MockRead(false, OK)
3385 };
3386
[email protected]5ecc992a42009-11-11 01:41:593387 StaticSocketDataProvider data(data_reads, data_writes);
3388 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353389
[email protected]5ecc992a42009-11-11 01:41:593390 SSLSocketDataProvider ssl(true, OK);
3391 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353392
3393 TestCompletionCallback callback;
3394
[email protected]684970b2009-08-14 04:54:463395 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353396 EXPECT_EQ(ERR_IO_PENDING, rv);
3397
3398 rv = callback.WaitForResult();
3399 EXPECT_EQ(OK, rv);
3400
3401 const HttpResponseInfo* response = trans->GetResponseInfo();
3402 EXPECT_FALSE(response == NULL);
3403
3404 std::string response_text;
3405 rv = ReadTransaction(trans.get(), &response_text);
3406 EXPECT_EQ(OK, rv);
3407 EXPECT_EQ("Payload", response_text);
3408}
3409
3410TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093411 SessionDependencies session_deps(
3412 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353413
3414 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433415 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353416
3417 HttpRequestInfo request;
3418 request.method = "GET";
3419 request.url = GURL("http://www.google.com/");
3420 request.load_flags = 0;
3421
3422 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3423 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373424 const char kSOCKS5OkRequest[] = {
3425 0x05, // Version
3426 0x01, // Command (CONNECT)
3427 0x00, // Reserved.
3428 0x03, // Address type (DOMAINNAME).
3429 0x0E, // Length of domain (14)
3430 // Domain string:
3431 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3432 0x00, 0x50, // 16-bit port (80)
3433 };
[email protected]e0c27be2009-07-15 13:09:353434 const char kSOCKS5OkResponse[] =
3435 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3436
3437 MockWrite data_writes[] = {
3438 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3439 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3440 MockWrite("GET / HTTP/1.1\r\n"
3441 "Host: www.google.com\r\n"
3442 "Connection: keep-alive\r\n\r\n")
3443 };
3444
3445 MockRead data_reads[] = {
3446 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3447 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3448 MockRead("HTTP/1.0 200 OK\r\n"),
3449 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3450 MockRead("Payload"),
3451 MockRead(false, OK)
3452 };
3453
[email protected]5ecc992a42009-11-11 01:41:593454 StaticSocketDataProvider data(data_reads, data_writes);
3455 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353456
3457 TestCompletionCallback callback;
3458
[email protected]684970b2009-08-14 04:54:463459 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353460 EXPECT_EQ(ERR_IO_PENDING, rv);
3461
3462 rv = callback.WaitForResult();
3463 EXPECT_EQ(OK, rv);
3464
3465 const HttpResponseInfo* response = trans->GetResponseInfo();
3466 EXPECT_FALSE(response == NULL);
3467
3468 std::string response_text;
3469 rv = ReadTransaction(trans.get(), &response_text);
3470 EXPECT_EQ(OK, rv);
3471 EXPECT_EQ("Payload", response_text);
3472}
3473
3474TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093475 SessionDependencies session_deps(
3476 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353477
3478 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433479 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353480
3481 HttpRequestInfo request;
3482 request.method = "GET";
3483 request.url = GURL("https://www.google.com/");
3484 request.load_flags = 0;
3485
3486 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3487 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373488 const unsigned char kSOCKS5OkRequest[] = {
3489 0x05, // Version
3490 0x01, // Command (CONNECT)
3491 0x00, // Reserved.
3492 0x03, // Address type (DOMAINNAME).
3493 0x0E, // Length of domain (14)
3494 // Domain string:
3495 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3496 0x01, 0xBB, // 16-bit port (443)
3497 };
3498
[email protected]e0c27be2009-07-15 13:09:353499 const char kSOCKS5OkResponse[] =
3500 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3501
3502 MockWrite data_writes[] = {
3503 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3504 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3505 arraysize(kSOCKS5OkRequest)),
3506 MockWrite("GET / HTTP/1.1\r\n"
3507 "Host: www.google.com\r\n"
3508 "Connection: keep-alive\r\n\r\n")
3509 };
3510
3511 MockRead data_reads[] = {
3512 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3513 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023514 MockRead("HTTP/1.0 200 OK\r\n"),
3515 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3516 MockRead("Payload"),
3517 MockRead(false, OK)
3518 };
3519
[email protected]5ecc992a42009-11-11 01:41:593520 StaticSocketDataProvider data(data_reads, data_writes);
3521 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023522
[email protected]5ecc992a42009-11-11 01:41:593523 SSLSocketDataProvider ssl(true, OK);
3524 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023525
3526 TestCompletionCallback callback;
3527
[email protected]684970b2009-08-14 04:54:463528 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023529 EXPECT_EQ(ERR_IO_PENDING, rv);
3530
3531 rv = callback.WaitForResult();
3532 EXPECT_EQ(OK, rv);
3533
3534 const HttpResponseInfo* response = trans->GetResponseInfo();
3535 EXPECT_FALSE(response == NULL);
3536
3537 std::string response_text;
3538 rv = ReadTransaction(trans.get(), &response_text);
3539 EXPECT_EQ(OK, rv);
3540 EXPECT_EQ("Payload", response_text);
3541}
3542
[email protected]04e5be32009-06-26 20:00:313543// Tests that for connection endpoints the group names are correctly set.
3544TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3545 const struct {
3546 const std::string proxy_server;
3547 const std::string url;
3548 const std::string expected_group_name;
3549 } tests[] = {
3550 {
3551 "", // no proxy (direct)
3552 "http://www.google.com/direct",
3553 "http://www.google.com/",
3554 },
3555 {
3556 "http_proxy",
3557 "http://www.google.com/http_proxy_normal",
3558 "proxy/http_proxy:80/",
3559 },
3560 {
3561 "socks4://socks_proxy:1080",
3562 "http://www.google.com/socks4_direct",
3563 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3564 },
3565
3566 // SSL Tests
3567 {
3568 "",
3569 "https://www.google.com/direct_ssl",
3570 "https://www.google.com/",
3571 },
3572 {
3573 "http_proxy",
3574 "https://www.google.com/http_connect_ssl",
3575 "proxy/http_proxy:80/https://www.google.com/",
3576 },
3577 {
3578 "socks4://socks_proxy:1080",
3579 "https://www.google.com/socks4_ssl",
3580 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3581 },
3582 };
3583
3584 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093585 SessionDependencies session_deps(
3586 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313587
3588 scoped_refptr<CaptureGroupNameSocketPool> conn_pool(
3589 new CaptureGroupNameSocketPool());
3590
3591 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a937a06d2009-08-19 21:19:243592 session->tcp_socket_pool_ = conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313593
[email protected]5695b8c2009-09-30 21:36:433594 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313595
3596 HttpRequestInfo request;
3597 request.method = "GET";
3598 request.url = GURL(tests[i].url);
3599 request.load_flags = 0;
3600
3601 TestCompletionCallback callback;
3602
3603 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463604 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]04e5be32009-06-26 20:00:313605 EXPECT_EQ(tests[i].expected_group_name,
3606 conn_pool->last_group_name_received());
3607 }
3608}
3609
[email protected]9172a982009-06-06 00:30:253610TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543611 SessionDependencies session_deps(
3612 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323613
[email protected]69719062010-01-05 20:09:213614 // This simulates failure resolving all hostnames; that means we will fail
3615 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:323616 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3617
[email protected]9172a982009-06-06 00:30:253618 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433619 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253620
3621 HttpRequestInfo request;
3622 request.method = "GET";
3623 request.url = GURL("http://www.google.com/");
3624
3625 TestCompletionCallback callback;
3626
[email protected]684970b2009-08-14 04:54:463627 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253628 EXPECT_EQ(ERR_IO_PENDING, rv);
3629
[email protected]9172a982009-06-06 00:30:253630 rv = callback.WaitForResult();
3631 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3632}
3633
[email protected]f3e6c1e2009-06-15 20:52:123634// Host resolution observer used by
3635// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3636// resovle requests are issued with a referrer of |expected_referrer|.
3637class ResolutionReferrerObserver : public HostResolver::Observer {
3638 public:
3639 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3640 : expected_referrer_(expected_referrer),
3641 called_start_with_referrer_(false),
3642 called_finish_with_referrer_(false) {
3643 }
3644
3645 virtual void OnStartResolution(int id,
3646 const HostResolver::RequestInfo& info) {
3647 if (info.referrer() == expected_referrer_)
3648 called_start_with_referrer_ = true;
3649 }
3650
3651 virtual void OnFinishResolutionWithStatus(
3652 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3653 if (info.referrer() == expected_referrer_)
3654 called_finish_with_referrer_ = true;
3655 }
3656
[email protected]eb255d32009-06-17 02:11:033657 virtual void OnCancelResolution(int id,
3658 const HostResolver::RequestInfo& info ) {
3659 FAIL() << "Should not be cancelling any requests!";
3660 }
3661
[email protected]f3e6c1e2009-06-15 20:52:123662 bool did_complete_with_expected_referrer() const {
3663 return called_start_with_referrer_ && called_finish_with_referrer_;
3664 }
3665
3666 private:
3667 GURL expected_referrer_;
3668 bool called_start_with_referrer_;
3669 bool called_finish_with_referrer_;
3670
3671 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3672};
3673
3674// Make sure that when HostResolver::Resolve() is invoked, it passes through
3675// the "referrer". This is depended on by the DNS prefetch observer.
3676TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3677 GURL referrer = GURL("http://expected-referrer/");
3678 EXPECT_TRUE(referrer.is_valid());
3679 ResolutionReferrerObserver resolution_observer(referrer);
3680
3681 SessionDependencies session_deps;
3682 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433683 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123684
3685 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143686 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123687
3688 // Connect up a mock socket which will fail when reading.
3689 MockRead data_reads[] = {
3690 MockRead(false, ERR_FAILED),
3691 };
[email protected]5ecc992a42009-11-11 01:41:593692 StaticSocketDataProvider data(data_reads, NULL);
3693 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:123694
3695 // Issue a request, containing an HTTP referrer.
3696 HttpRequestInfo request;
3697 request.method = "GET";
3698 request.referrer = referrer;
3699 request.url = GURL("http://www.google.com/");
3700
3701 // Run the request until it fails reading from the socket.
3702 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463703 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123704 EXPECT_EQ(ERR_IO_PENDING, rv);
3705 rv = callback.WaitForResult();
3706 EXPECT_EQ(ERR_FAILED, rv);
3707
3708 // Check that the host resolution observer saw |referrer|.
3709 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3710}
3711
[email protected]3b9cca42009-06-16 01:08:283712// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3713// host cache is bypassed.
3714TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3715 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323716
[email protected]a2c2fb92009-07-18 07:31:043717 // Select a host resolver that does caching.
3718 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323719
[email protected]3b9cca42009-06-16 01:08:283720 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433721 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:283722
3723 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3724 // a synchronous lookup.)
3725 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143726 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463727 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3728 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283729 EXPECT_EQ(OK, rv);
3730
3731 // Verify that it was added to host cache, by doing a subsequent async lookup
3732 // and confirming it completes synchronously.
3733 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463734 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283735 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463736 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323737 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283738
3739 // Inject a failure the next time that "www.google.com" is resolved. This way
3740 // we can tell if the next lookup hit the cache, or the "network".
3741 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323742 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283743
3744 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3745 // first read -- this won't be reached as the host resolution will fail first.
3746 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]5ecc992a42009-11-11 01:41:593747 StaticSocketDataProvider data(data_reads, NULL);
3748 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:283749
3750 // Issue a request, asking to bypass the cache(s).
3751 HttpRequestInfo request;
3752 request.method = "GET";
3753 request.load_flags = LOAD_BYPASS_CACHE;
3754 request.url = GURL("http://www.google.com/");
3755
3756 // Run the request.
3757 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463758 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283759 ASSERT_EQ(ERR_IO_PENDING, rv);
3760 rv = callback.WaitForResult();
3761
3762 // If we bypassed the cache, we would have gotten a failure while resolving
3763 // "www.google.com".
3764 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3765}
3766
[email protected]0877e3d2009-10-17 22:29:573767// Make sure we can handle an error when writing the request.
3768TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3769 SessionDependencies session_deps;
3770 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3771
3772 HttpRequestInfo request;
3773 request.method = "GET";
3774 request.url = GURL("http://www.foo.com/");
3775 request.load_flags = 0;
3776
3777 MockWrite write_failure[] = {
3778 MockWrite(true, ERR_CONNECTION_RESET),
3779 };
[email protected]5ecc992a42009-11-11 01:41:593780 StaticSocketDataProvider data(NULL, write_failure);
3781 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573782
3783 TestCompletionCallback callback;
3784
3785 scoped_ptr<HttpTransaction> trans(
3786 new HttpNetworkTransaction(CreateSession(&session_deps)));
3787
3788 int rv = trans->Start(&request, &callback, NULL);
3789 EXPECT_EQ(ERR_IO_PENDING, rv);
3790
3791 rv = callback.WaitForResult();
3792 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3793}
3794
3795// Check that a connection closed after the start of the headers finishes ok.
3796TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3797 SessionDependencies session_deps;
3798 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3799
3800 HttpRequestInfo request;
3801 request.method = "GET";
3802 request.url = GURL("http://www.foo.com/");
3803 request.load_flags = 0;
3804
3805 MockRead data_reads[] = {
3806 MockRead("HTTP/1."),
3807 MockRead(false, OK),
3808 };
3809
[email protected]5ecc992a42009-11-11 01:41:593810 StaticSocketDataProvider data(data_reads, NULL);
3811 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573812
3813 TestCompletionCallback callback;
3814
3815 scoped_ptr<HttpTransaction> trans(
3816 new HttpNetworkTransaction(CreateSession(&session_deps)));
3817
3818 int rv = trans->Start(&request, &callback, NULL);
3819 EXPECT_EQ(ERR_IO_PENDING, rv);
3820
3821 rv = callback.WaitForResult();
3822 EXPECT_EQ(OK, rv);
3823
3824 const HttpResponseInfo* response = trans->GetResponseInfo();
3825 EXPECT_TRUE(response != NULL);
3826
3827 EXPECT_TRUE(response->headers != NULL);
3828 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
3829
3830 std::string response_data;
3831 rv = ReadTransaction(trans.get(), &response_data);
3832 EXPECT_EQ(OK, rv);
3833 EXPECT_EQ("", response_data);
3834}
3835
3836// Make sure that a dropped connection while draining the body for auth
3837// restart does the right thing.
3838TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
3839 SessionDependencies session_deps;
3840 scoped_ptr<HttpTransaction> trans(
3841 new HttpNetworkTransaction(CreateSession(&session_deps)));
3842
3843 HttpRequestInfo request;
3844 request.method = "GET";
3845 request.url = GURL("http://www.google.com/");
3846 request.load_flags = 0;
3847
3848 MockWrite data_writes1[] = {
3849 MockWrite("GET / HTTP/1.1\r\n"
3850 "Host: www.google.com\r\n"
3851 "Connection: keep-alive\r\n\r\n"),
3852 };
3853
3854 MockRead data_reads1[] = {
3855 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3856 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3857 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3858 MockRead("Content-Length: 14\r\n\r\n"),
3859 MockRead("Unauth"),
3860 MockRead(true, ERR_CONNECTION_RESET),
3861 };
3862
[email protected]5ecc992a42009-11-11 01:41:593863 StaticSocketDataProvider data1(data_reads1, data_writes1);
3864 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:573865
3866 // After calling trans->RestartWithAuth(), this is the request we should
3867 // be issuing -- the final header line contains the credentials.
3868 MockWrite data_writes2[] = {
3869 MockWrite("GET / HTTP/1.1\r\n"
3870 "Host: www.google.com\r\n"
3871 "Connection: keep-alive\r\n"
3872 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3873 };
3874
3875 // Lastly, the server responds with the actual content.
3876 MockRead data_reads2[] = {
3877 MockRead("HTTP/1.1 200 OK\r\n"),
3878 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3879 MockRead("Content-Length: 100\r\n\r\n"),
3880 MockRead(false, OK),
3881 };
3882
[email protected]5ecc992a42009-11-11 01:41:593883 StaticSocketDataProvider data2(data_reads2, data_writes2);
3884 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:573885
3886 TestCompletionCallback callback1;
3887
3888 int rv = trans->Start(&request, &callback1, NULL);
3889 EXPECT_EQ(ERR_IO_PENDING, rv);
3890
3891 rv = callback1.WaitForResult();
3892 EXPECT_EQ(OK, rv);
3893
3894 const HttpResponseInfo* response = trans->GetResponseInfo();
3895 EXPECT_FALSE(response == NULL);
3896
3897 // The password prompt info should have been set in response->auth_challenge.
3898 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3899
3900 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3901 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3902 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3903
3904 TestCompletionCallback callback2;
3905
3906 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3907 EXPECT_EQ(ERR_IO_PENDING, rv);
3908
3909 rv = callback2.WaitForResult();
3910 EXPECT_EQ(OK, rv);
3911
3912 response = trans->GetResponseInfo();
3913 EXPECT_FALSE(response == NULL);
3914 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3915 EXPECT_EQ(100, response->headers->GetContentLength());
3916}
3917
3918// Test HTTPS connections going through a proxy that sends extra data.
3919TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
3920 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
3921
3922 HttpRequestInfo request;
3923 request.method = "GET";
3924 request.url = GURL("https://www.google.com/");
3925 request.load_flags = 0;
3926
3927 MockRead proxy_reads[] = {
3928 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
3929 MockRead(false, OK)
3930 };
3931
[email protected]5ecc992a42009-11-11 01:41:593932 StaticSocketDataProvider data(proxy_reads, NULL);
3933 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:573934
[email protected]5ecc992a42009-11-11 01:41:593935 session_deps.socket_factory.AddSocketDataProvider(&data);
3936 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:573937
3938 TestCompletionCallback callback;
3939
3940 session_deps.socket_factory.ResetNextMockIndexes();
3941
3942 scoped_ptr<HttpTransaction> trans(
3943 new HttpNetworkTransaction(CreateSession(&session_deps)));
3944
3945 int rv = trans->Start(&request, &callback, NULL);
3946 EXPECT_EQ(ERR_IO_PENDING, rv);
3947
3948 rv = callback.WaitForResult();
3949 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3950}
3951
[email protected]e22e1362009-11-23 21:31:123952TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
3953 MockRead data_reads[] = {
3954 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
3955 MockRead(false, OK),
3956 };
3957 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
3958 EXPECT_EQ(OK, out.rv);
3959 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
3960 EXPECT_EQ("", out.response_data);
3961}
3962
[email protected]95d88ffe2010-02-04 21:25:333963TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
3964 SessionDependencies session_deps;
3965 scoped_ptr<HttpTransaction> trans(
3966 new HttpNetworkTransaction(CreateSession(&session_deps)));
3967
3968 HttpRequestInfo request;
3969 request.method = "POST";
3970 request.url = GURL("http://www.google.com/upload");
3971 request.upload_data = new UploadData;
3972 request.load_flags = 0;
3973
3974 FilePath temp_file_path;
3975 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
3976 const uint64 kFakeSize = 100000; // file is actually blank
3977
3978 std::vector<UploadData::Element> elements;
3979 UploadData::Element element;
3980 element.SetToFilePath(temp_file_path);
3981 element.SetContentLength(kFakeSize);
3982 elements.push_back(element);
3983 request.upload_data->set_elements(elements);
3984 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
3985
3986 MockRead data_reads[] = {
3987 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
3988 MockRead("hello world"),
3989 MockRead(false, OK),
3990 };
3991 StaticSocketDataProvider data(data_reads, NULL);
3992 session_deps.socket_factory.AddSocketDataProvider(&data);
3993
3994 TestCompletionCallback callback;
3995
3996 int rv = trans->Start(&request, &callback, NULL);
3997 EXPECT_EQ(ERR_IO_PENDING, rv);
3998
3999 rv = callback.WaitForResult();
4000 EXPECT_EQ(OK, rv);
4001
4002 const HttpResponseInfo* response = trans->GetResponseInfo();
4003 EXPECT_TRUE(response != NULL);
4004
4005 EXPECT_TRUE(response->headers != NULL);
4006 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4007
4008 std::string response_data;
4009 rv = ReadTransaction(trans.get(), &response_data);
4010 EXPECT_EQ(OK, rv);
4011 EXPECT_EQ("hello world", response_data);
4012
4013 file_util::Delete(temp_file_path, false);
4014}
4015
[email protected]89ceba9a2009-03-21 03:46:064016} // namespace net