blob: d929075e3b278fd0d20957bee31ad04d8298d3f9 [file] [log] [blame]
[email protected]9b6fee12009-09-29 18:13:071// Copyright (c) 2009 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
6
[email protected]68bf9152008-09-25 19:47:307#include "base/compiler_specific.h"
[email protected]bacff652009-03-31 17:50:338#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:329#include "net/base/mock_host_resolver.h"
[email protected]db36938c2009-08-19 21:48:4210#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3311#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5212#include "net/base/test_completion_callback.h"
13#include "net/base/upload_data.h"
[email protected]d1eda932009-11-04 01:03:1014#include "net/flip/flip_session_pool.h"
[email protected]385a4672009-03-11 22:21:2915#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5716#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5217#include "net/http/http_network_session.h"
18#include "net/http/http_network_transaction.h"
[email protected]0877e3d2009-10-17 22:29:5719#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5220#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5321#include "net/proxy/proxy_config_service_fixed.h"
[email protected]f7984fc62009-06-22 23:26:4422#include "net/socket/client_socket_factory.h"
23#include "net/socket/socket_test_util.h"
24#include "net/socket/ssl_client_socket.h"
initial.commit586acc5fe2008-07-26 22:42:5225#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1526#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5227
28//-----------------------------------------------------------------------------
29
[email protected]89ceba9a2009-03-21 03:46:0630namespace net {
31
[email protected]db8f44c2008-12-13 04:52:0132// Create a proxy service which fails on all requests (falls back to direct).
[email protected]1c773ea12009-04-28 19:58:4233ProxyService* CreateNullProxyService() {
34 return ProxyService::CreateNull();
initial.commit586acc5fe2008-07-26 22:42:5235}
36
[email protected]e44de5d2009-06-05 20:12:4537// Helper to manage the lifetimes of the dependencies for a
38// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5939class SessionDependencies {
40 public:
41 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4242 SessionDependencies()
43 : host_resolver(new MockHostResolver),
44 proxy_service(CreateNullProxyService()),
[email protected]d1eda932009-11-04 01:03:1045 ssl_config_service(new SSLConfigServiceDefaults),
46 flip_session_pool(new FlipSessionPool) {}
[email protected]228ff742009-06-05 01:19:5947
48 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4549 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4250 : host_resolver(new MockHostResolver),
51 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1052 ssl_config_service(new SSLConfigServiceDefaults),
53 flip_session_pool(new FlipSessionPool) {}
[email protected]228ff742009-06-05 01:19:5954
[email protected]a2c2fb92009-07-18 07:31:0455 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0956 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4257 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5958 MockClientSocketFactory socket_factory;
[email protected]d1eda932009-11-04 01:03:1059 scoped_refptr<FlipSessionPool> flip_session_pool;
[email protected]228ff742009-06-05 01:19:5960};
61
[email protected]1c773ea12009-04-28 19:58:4262ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5063 net::ProxyConfig proxy_config;
64 proxy_config.proxy_rules.ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3965 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5366}
67
68
[email protected]228ff742009-06-05 01:19:5969HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]94a0d3d92009-06-27 01:50:1470 return new HttpNetworkSession(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]69b43fe2009-06-15 09:47:37106 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59107 session_deps.socket_factory.AddMockSocket(&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]a937a06d2009-08-19 21:19:24182 CaptureGroupNameSocketPool() : TCPClientSocketPool(0, 0, 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]04e5be32009-06-26 20:00:31189 int priority,
190 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]69b43fe2009-06-15 09:47:37375 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59376 session_deps.socket_factory.AddMockSocket(&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]69b43fe2009-06-15 09:47:37420 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59421 session_deps.socket_factory.AddMockSocket(&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]69b43fe2009-06-15 09:47:37474 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59475 session_deps.socket_factory.AddMockSocket(&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]69b43fe2009-06-15 09:47:37516 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59517 session_deps.socket_factory.AddMockSocket(&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]3d2a59b2008-09-26 19:44:25539// read_failure specifies a read failure that should cause the network
540// transaction to resend the request.
541void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
542 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59543 SessionDependencies session_deps;
544 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52545
[email protected]1c773ea12009-04-28 19:58:42546 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52547 request.method = "GET";
548 request.url = GURL("http://www.foo.com/");
549 request.load_flags = 0;
550
551 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35552 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
553 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25554 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52555 };
[email protected]69b43fe2009-06-15 09:47:37556 StaticMockSocket data1(data1_reads, NULL);
[email protected]228ff742009-06-05 01:19:59557 session_deps.socket_factory.AddMockSocket(&data1);
initial.commit586acc5fe2008-07-26 22:42:52558
559 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35560 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
561 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42562 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52563 };
[email protected]69b43fe2009-06-15 09:47:37564 StaticMockSocket data2(data2_reads, NULL);
[email protected]228ff742009-06-05 01:19:59565 session_deps.socket_factory.AddMockSocket(&data2);
initial.commit586acc5fe2008-07-26 22:42:52566
567 const char* kExpectedResponseData[] = {
568 "hello", "world"
569 };
570
571 for (int i = 0; i < 2; ++i) {
572 TestCompletionCallback callback;
573
[email protected]5695b8c2009-09-30 21:36:43574 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52575
[email protected]684970b2009-08-14 04:54:46576 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42577 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52578
579 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42580 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52581
[email protected]1c773ea12009-04-28 19:58:42582 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52583 EXPECT_TRUE(response != NULL);
584
585 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25586 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52587
588 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57589 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42590 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25591 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52592 }
593}
[email protected]3d2a59b2008-09-26 19:44:25594
595TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42596 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25597 KeepAliveConnectionResendRequestTest(read_failure);
598}
599
600TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42601 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25602 KeepAliveConnectionResendRequestTest(read_failure);
603}
604
605TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59606 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40607 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43608 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25609
[email protected]1c773ea12009-04-28 19:58:42610 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25611 request.method = "GET";
612 request.url = GURL("http://www.google.com/");
613 request.load_flags = 0;
614
615 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42616 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35617 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
618 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42619 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25620 };
[email protected]69b43fe2009-06-15 09:47:37621 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59622 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3d2a59b2008-09-26 19:44:25623
624 TestCompletionCallback callback;
625
[email protected]684970b2009-08-14 04:54:46626 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42627 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25628
629 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42630 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25631
[email protected]1c773ea12009-04-28 19:58:42632 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25633 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25634}
635
636// What do various browsers do when the server closes a non-keepalive
637// connection without sending any response header or body?
638//
639// IE7: error page
640// Safari 3.1.2 (Windows): error page
641// Firefox 3.0.1: blank page
642// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42643// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
644// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25645TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
646 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42647 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35648 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
649 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42650 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25651 };
652 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42653 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25654}
[email protected]038e9a32008-10-08 22:40:16655
656// Test the request-challenge-retry sequence for basic auth.
657// (basic auth is the easiest to mock, because it has no randomness).
658TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59659 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40660 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43661 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16662
[email protected]1c773ea12009-04-28 19:58:42663 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16664 request.method = "GET";
665 request.url = GURL("http://www.google.com/");
666 request.load_flags = 0;
667
[email protected]f9ee6b52008-11-08 06:46:23668 MockWrite data_writes1[] = {
669 MockWrite("GET / HTTP/1.1\r\n"
670 "Host: www.google.com\r\n"
671 "Connection: keep-alive\r\n\r\n"),
672 };
673
[email protected]038e9a32008-10-08 22:40:16674 MockRead data_reads1[] = {
675 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
676 // Give a couple authenticate options (only the middle one is actually
677 // supported).
[email protected]22927ad2009-09-21 19:56:19678 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16679 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
680 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
681 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
682 // Large content-length -- won't matter, as connection will be reset.
683 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42684 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16685 };
686
687 // After calling trans->RestartWithAuth(), this is the request we should
688 // be issuing -- the final header line contains the credentials.
689 MockWrite data_writes2[] = {
690 MockWrite("GET / HTTP/1.1\r\n"
691 "Host: www.google.com\r\n"
692 "Connection: keep-alive\r\n"
693 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
694 };
695
696 // Lastly, the server responds with the actual content.
697 MockRead data_reads2[] = {
698 MockRead("HTTP/1.0 200 OK\r\n"),
699 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
700 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42701 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16702 };
703
[email protected]69b43fe2009-06-15 09:47:37704 StaticMockSocket data1(data_reads1, data_writes1);
705 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:59706 session_deps.socket_factory.AddMockSocket(&data1);
707 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]038e9a32008-10-08 22:40:16708
709 TestCompletionCallback callback1;
710
[email protected]684970b2009-08-14 04:54:46711 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42712 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16713
714 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42715 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16716
[email protected]1c773ea12009-04-28 19:58:42717 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16718 EXPECT_FALSE(response == NULL);
719
720 // The password prompt info should have been set in response->auth_challenge.
721 EXPECT_FALSE(response->auth_challenge.get() == NULL);
722
[email protected]71e4573a2009-05-21 22:03:00723 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16724 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
725 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
726
727 TestCompletionCallback callback2;
728
729 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42730 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16731
732 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42733 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16734
735 response = trans->GetResponseInfo();
736 EXPECT_FALSE(response == NULL);
737 EXPECT_TRUE(response->auth_challenge.get() == NULL);
738 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16739}
740
[email protected]861fcd52009-08-26 02:33:46741TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
742 SessionDependencies session_deps;
743 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43744 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46745
746 HttpRequestInfo request;
747 request.method = "GET";
748 request.url = GURL("http://www.google.com/");
749 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
750
751 MockWrite data_writes[] = {
752 MockWrite("GET / HTTP/1.1\r\n"
753 "Host: www.google.com\r\n"
754 "Connection: keep-alive\r\n\r\n"),
755 };
756
757 MockRead data_reads[] = {
758 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
759 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
760 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
761 // Large content-length -- won't matter, as connection will be reset.
762 MockRead("Content-Length: 10000\r\n\r\n"),
763 MockRead(false, ERR_FAILED),
764 };
765
766 StaticMockSocket data(data_reads, data_writes);
767 session_deps.socket_factory.AddMockSocket(&data);
768 TestCompletionCallback callback;
769
770 int rv = trans->Start(&request, &callback, NULL);
771 EXPECT_EQ(ERR_IO_PENDING, rv);
772
773 rv = callback.WaitForResult();
774 EXPECT_EQ(0, rv);
775
776 const HttpResponseInfo* response = trans->GetResponseInfo();
777 ASSERT_FALSE(response == NULL);
778 EXPECT_TRUE(response->auth_challenge.get() == NULL);
779}
780
[email protected]2d2697f92009-02-18 21:00:32781// Test the request-challenge-retry sequence for basic auth, over a keep-alive
782// connection.
783TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59784 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40785 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43786 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32787
[email protected]1c773ea12009-04-28 19:58:42788 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32789 request.method = "GET";
790 request.url = GURL("http://www.google.com/");
791 request.load_flags = 0;
792
793 MockWrite data_writes1[] = {
794 MockWrite("GET / HTTP/1.1\r\n"
795 "Host: www.google.com\r\n"
796 "Connection: keep-alive\r\n\r\n"),
797
798 // After calling trans->RestartWithAuth(), this is the request we should
799 // be issuing -- the final header line contains the credentials.
800 MockWrite("GET / HTTP/1.1\r\n"
801 "Host: www.google.com\r\n"
802 "Connection: keep-alive\r\n"
803 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
804 };
805
806 MockRead data_reads1[] = {
807 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
808 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
809 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
810 MockRead("Content-Length: 14\r\n\r\n"),
811 MockRead("Unauthorized\r\n"),
812
813 // Lastly, the server responds with the actual content.
814 MockRead("HTTP/1.1 200 OK\r\n"),
815 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
816 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42817 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32818 };
819
[email protected]69b43fe2009-06-15 09:47:37820 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59821 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32822
823 TestCompletionCallback callback1;
824
[email protected]684970b2009-08-14 04:54:46825 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42826 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32827
828 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42829 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32830
[email protected]1c773ea12009-04-28 19:58:42831 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32832 EXPECT_FALSE(response == NULL);
833
834 // The password prompt info should have been set in response->auth_challenge.
835 EXPECT_FALSE(response->auth_challenge.get() == NULL);
836
[email protected]71e4573a2009-05-21 22:03:00837 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32838 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
839 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
840
841 TestCompletionCallback callback2;
842
843 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42844 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32845
846 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42847 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32848
849 response = trans->GetResponseInfo();
850 EXPECT_FALSE(response == NULL);
851 EXPECT_TRUE(response->auth_challenge.get() == NULL);
852 EXPECT_EQ(100, response->headers->GetContentLength());
853}
854
855// Test the request-challenge-retry sequence for basic auth, over a keep-alive
856// connection and with no response body to drain.
857TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59858 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40859 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43860 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32861
[email protected]1c773ea12009-04-28 19:58:42862 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32863 request.method = "GET";
864 request.url = GURL("http://www.google.com/");
865 request.load_flags = 0;
866
867 MockWrite data_writes1[] = {
868 MockWrite("GET / HTTP/1.1\r\n"
869 "Host: www.google.com\r\n"
870 "Connection: keep-alive\r\n\r\n"),
871
872 // After calling trans->RestartWithAuth(), this is the request we should
873 // be issuing -- the final header line contains the credentials.
874 MockWrite("GET / HTTP/1.1\r\n"
875 "Host: www.google.com\r\n"
876 "Connection: keep-alive\r\n"
877 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
878 };
879
880 // Respond with 5 kb of response body.
881 std::string large_body_string("Unauthorized");
882 large_body_string.append(5 * 1024, ' ');
883 large_body_string.append("\r\n");
884
885 MockRead data_reads1[] = {
886 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
887 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
888 MockRead("Content-Length: 0\r\n\r\n"),
889
890 // Lastly, the server responds with the actual content.
891 MockRead("HTTP/1.1 200 OK\r\n"),
892 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
893 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42894 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32895 };
896
[email protected]69b43fe2009-06-15 09:47:37897 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59898 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32899
900 TestCompletionCallback callback1;
901
[email protected]684970b2009-08-14 04:54:46902 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42903 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32904
905 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42906 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32907
[email protected]1c773ea12009-04-28 19:58:42908 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32909 EXPECT_FALSE(response == NULL);
910
911 // The password prompt info should have been set in response->auth_challenge.
912 EXPECT_FALSE(response->auth_challenge.get() == NULL);
913
[email protected]71e4573a2009-05-21 22:03:00914 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32915 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
916 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
917
918 TestCompletionCallback callback2;
919
920 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42921 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32922
923 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42924 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32925
926 response = trans->GetResponseInfo();
927 EXPECT_FALSE(response == NULL);
928 EXPECT_TRUE(response->auth_challenge.get() == NULL);
929 EXPECT_EQ(100, response->headers->GetContentLength());
930}
931
932// Test the request-challenge-retry sequence for basic auth, over a keep-alive
933// connection and with a large response body to drain.
934TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:59935 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40936 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43937 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32938
[email protected]1c773ea12009-04-28 19:58:42939 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32940 request.method = "GET";
941 request.url = GURL("http://www.google.com/");
942 request.load_flags = 0;
943
944 MockWrite data_writes1[] = {
945 MockWrite("GET / HTTP/1.1\r\n"
946 "Host: www.google.com\r\n"
947 "Connection: keep-alive\r\n\r\n"),
948
949 // After calling trans->RestartWithAuth(), this is the request we should
950 // be issuing -- the final header line contains the credentials.
951 MockWrite("GET / HTTP/1.1\r\n"
952 "Host: www.google.com\r\n"
953 "Connection: keep-alive\r\n"
954 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
955 };
956
957 // Respond with 5 kb of response body.
958 std::string large_body_string("Unauthorized");
959 large_body_string.append(5 * 1024, ' ');
960 large_body_string.append("\r\n");
961
962 MockRead data_reads1[] = {
963 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
964 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
965 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
966 // 5134 = 12 + 5 * 1024 + 2
967 MockRead("Content-Length: 5134\r\n\r\n"),
968 MockRead(true, large_body_string.data(), large_body_string.size()),
969
970 // Lastly, the server responds with the actual content.
971 MockRead("HTTP/1.1 200 OK\r\n"),
972 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
973 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42974 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32975 };
976
[email protected]69b43fe2009-06-15 09:47:37977 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59978 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32979
980 TestCompletionCallback callback1;
981
[email protected]684970b2009-08-14 04:54:46982 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42983 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32984
985 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42986 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32987
[email protected]1c773ea12009-04-28 19:58:42988 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32989 EXPECT_FALSE(response == NULL);
990
991 // The password prompt info should have been set in response->auth_challenge.
992 EXPECT_FALSE(response->auth_challenge.get() == NULL);
993
[email protected]71e4573a2009-05-21 22:03:00994 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32995 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
996 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
997
998 TestCompletionCallback callback2;
999
1000 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421001 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321002
1003 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421004 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321005
1006 response = trans->GetResponseInfo();
1007 EXPECT_FALSE(response == NULL);
1008 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1009 EXPECT_EQ(100, response->headers->GetContentLength());
1010}
1011
1012// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1013// proxy connection, when setting up an SSL tunnel.
1014TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1015 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591016 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1017 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321018
[email protected]5695b8c2009-09-30 21:36:431019 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321020
[email protected]1c773ea12009-04-28 19:58:421021 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321022 request.method = "GET";
1023 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461024 // Ensure that proxy authentication is attempted even
1025 // when the no authentication data flag is set.
1026 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321027
1028 // Since we have proxy, should try to establish tunnel.
1029 MockWrite data_writes1[] = {
1030 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451031 "Host: www.google.com\r\n"
1032 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321033
1034 // After calling trans->RestartWithAuth(), this is the request we should
1035 // be issuing -- the final header line contains the credentials.
1036 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1037 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451038 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321039 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1040 };
1041
1042 // The proxy responds to the connect with a 407, using a persistent
1043 // connection.
1044 MockRead data_reads1[] = {
1045 // No credentials.
1046 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1047 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1048 MockRead("Content-Length: 10\r\n\r\n"),
1049 MockRead("0123456789"),
1050
1051 // Wrong credentials (wrong password).
1052 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1053 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1054 MockRead("Content-Length: 10\r\n\r\n"),
1055 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421056 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321057 };
1058
[email protected]69b43fe2009-06-15 09:47:371059 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:591060 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:321061
1062 TestCompletionCallback callback1;
1063
[email protected]684970b2009-08-14 04:54:461064 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421065 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321066
1067 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421068 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321069
[email protected]1c773ea12009-04-28 19:58:421070 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321071 EXPECT_FALSE(response == NULL);
1072
1073 EXPECT_TRUE(response->headers->IsKeepAlive());
1074 EXPECT_EQ(407, response->headers->response_code());
1075 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421076 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321077
1078 // The password prompt info should have been set in response->auth_challenge.
1079 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1080
[email protected]71e4573a2009-05-21 22:03:001081 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321082 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1083 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1084
1085 TestCompletionCallback callback2;
1086
1087 // Wrong password (should be "bar").
1088 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421089 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321090
1091 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421092 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321093
1094 response = trans->GetResponseInfo();
1095 EXPECT_FALSE(response == NULL);
1096
1097 EXPECT_TRUE(response->headers->IsKeepAlive());
1098 EXPECT_EQ(407, response->headers->response_code());
1099 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421100 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321101
1102 // The password prompt info should have been set in response->auth_challenge.
1103 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1104
[email protected]71e4573a2009-05-21 22:03:001105 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321106 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1107 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1108}
1109
[email protected]a8e9b162009-03-12 00:06:441110// Test that we don't read the response body when we fail to establish a tunnel,
1111// even if the user cancels the proxy's auth attempt.
1112TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1113 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591114 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441115
[email protected]e44de5d2009-06-05 20:12:451116 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441117
[email protected]5695b8c2009-09-30 21:36:431118 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441119
[email protected]1c773ea12009-04-28 19:58:421120 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441121 request.method = "GET";
1122 request.url = GURL("https://www.google.com/");
1123 request.load_flags = 0;
1124
1125 // Since we have proxy, should try to establish tunnel.
1126 MockWrite data_writes[] = {
1127 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451128 "Host: www.google.com\r\n"
1129 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441130 };
1131
1132 // The proxy responds to the connect with a 407.
1133 MockRead data_reads[] = {
1134 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1135 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1136 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421137 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441138 };
1139
[email protected]69b43fe2009-06-15 09:47:371140 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:591141 session_deps.socket_factory.AddMockSocket(&data);
[email protected]a8e9b162009-03-12 00:06:441142
1143 TestCompletionCallback callback;
1144
[email protected]684970b2009-08-14 04:54:461145 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421146 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441147
1148 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421149 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441150
[email protected]1c773ea12009-04-28 19:58:421151 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441152 EXPECT_FALSE(response == NULL);
1153
1154 EXPECT_TRUE(response->headers->IsKeepAlive());
1155 EXPECT_EQ(407, response->headers->response_code());
1156 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421157 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441158
1159 std::string response_data;
1160 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421161 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441162}
1163
[email protected]ff007e162009-05-23 09:13:151164void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081165 const MockRead& status, int expected_status) {
1166 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591167 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081168
[email protected]228ff742009-06-05 01:19:591169 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081170
[email protected]5695b8c2009-09-30 21:36:431171 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081172
[email protected]1c773ea12009-04-28 19:58:421173 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081174 request.method = "GET";
1175 request.url = GURL("https://www.google.com/");
1176 request.load_flags = 0;
1177
1178 // Since we have proxy, should try to establish tunnel.
1179 MockWrite data_writes[] = {
1180 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451181 "Host: www.google.com\r\n"
1182 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081183 };
1184
1185 MockRead data_reads[] = {
1186 status,
1187 MockRead("Content-Length: 10\r\n\r\n"),
1188 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421189 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081190 };
1191
[email protected]69b43fe2009-06-15 09:47:371192 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:591193 session_deps.socket_factory.AddMockSocket(&data);
[email protected]c744cf22009-02-27 07:28:081194
1195 TestCompletionCallback callback;
1196
[email protected]684970b2009-08-14 04:54:461197 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421198 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081199
1200 rv = callback.WaitForResult();
1201 EXPECT_EQ(expected_status, rv);
1202}
1203
[email protected]ff007e162009-05-23 09:13:151204void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081205 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421206 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081207}
1208
1209TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1210 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1211}
1212
1213TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1214 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1215}
1216
1217TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1218 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1219}
1220
1221TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1222 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1223}
1224
1225TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1226 ConnectStatusHelper(
1227 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1228}
1229
1230TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1231 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1232}
1233
1234TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1235 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1236}
1237
1238TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1239 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1240}
1241
1242TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1243 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1244}
1245
1246TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1247 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1248}
1249
1250TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1251 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1252}
1253
1254TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1255 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1256}
1257
1258TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1259 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1260}
1261
1262TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1263 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1264}
1265
1266TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1267 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1268}
1269
1270TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1271 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1272}
1273
1274TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1275 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1276}
1277
1278TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1279 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1280}
1281
1282TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1283 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1284}
1285
1286TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1287 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1288}
1289
1290TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1291 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1292}
1293
1294TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1295 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1296}
1297
1298TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1299 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1300}
1301
1302TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1303 ConnectStatusHelperWithExpectedStatus(
1304 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421305 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081306}
1307
1308TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1309 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1310}
1311
1312TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1313 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1314}
1315
1316TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1317 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1318}
1319
1320TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1321 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1322}
1323
1324TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1325 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1326}
1327
1328TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1329 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1330}
1331
1332TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1333 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1334}
1335
1336TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1337 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1338}
1339
1340TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1341 ConnectStatusHelper(
1342 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1343}
1344
1345TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1346 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1347}
1348
1349TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1350 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1351}
1352
1353TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1354 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1355}
1356
1357TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1358 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1359}
1360
1361TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1362 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1363}
1364
1365TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1366 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1367}
1368
1369TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1370 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1371}
1372
[email protected]038e9a32008-10-08 22:40:161373// Test the flow when both the proxy server AND origin server require
1374// authentication. Again, this uses basic auth for both since that is
1375// the simplest to mock.
1376TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591377 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011378
[email protected]038e9a32008-10-08 22:40:161379 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421380 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431381 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161382
[email protected]1c773ea12009-04-28 19:58:421383 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161384 request.method = "GET";
1385 request.url = GURL("http://www.google.com/");
1386 request.load_flags = 0;
1387
[email protected]f9ee6b52008-11-08 06:46:231388 MockWrite data_writes1[] = {
1389 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1390 "Host: www.google.com\r\n"
1391 "Proxy-Connection: keep-alive\r\n\r\n"),
1392 };
1393
[email protected]038e9a32008-10-08 22:40:161394 MockRead data_reads1[] = {
1395 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1396 // Give a couple authenticate options (only the middle one is actually
1397 // supported).
[email protected]22927ad2009-09-21 19:56:191398 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161399 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1400 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1401 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1402 // Large content-length -- won't matter, as connection will be reset.
1403 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421404 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161405 };
1406
1407 // After calling trans->RestartWithAuth() the first time, this is the
1408 // request we should be issuing -- the final header line contains the
1409 // proxy's credentials.
1410 MockWrite data_writes2[] = {
1411 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1412 "Host: www.google.com\r\n"
1413 "Proxy-Connection: keep-alive\r\n"
1414 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1415 };
1416
1417 // Now the proxy server lets the request pass through to origin server.
1418 // The origin server responds with a 401.
1419 MockRead data_reads2[] = {
1420 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1421 // Note: We are using the same realm-name as the proxy server. This is
1422 // completely valid, as realms are unique across hosts.
1423 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1424 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1425 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421426 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161427 };
1428
1429 // After calling trans->RestartWithAuth() the second time, we should send
1430 // the credentials for both the proxy and origin server.
1431 MockWrite data_writes3[] = {
1432 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1433 "Host: www.google.com\r\n"
1434 "Proxy-Connection: keep-alive\r\n"
1435 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1436 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1437 };
1438
1439 // Lastly we get the desired content.
1440 MockRead data_reads3[] = {
1441 MockRead("HTTP/1.0 200 OK\r\n"),
1442 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1443 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421444 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161445 };
1446
[email protected]69b43fe2009-06-15 09:47:371447 StaticMockSocket data1(data_reads1, data_writes1);
1448 StaticMockSocket data2(data_reads2, data_writes2);
1449 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:591450 session_deps.socket_factory.AddMockSocket(&data1);
1451 session_deps.socket_factory.AddMockSocket(&data2);
1452 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]038e9a32008-10-08 22:40:161453
1454 TestCompletionCallback callback1;
1455
[email protected]684970b2009-08-14 04:54:461456 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421457 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161458
1459 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421460 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161461
[email protected]1c773ea12009-04-28 19:58:421462 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161463 EXPECT_FALSE(response == NULL);
1464
1465 // The password prompt info should have been set in response->auth_challenge.
1466 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1467
[email protected]71e4573a2009-05-21 22:03:001468 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161469 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1470 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1471
1472 TestCompletionCallback callback2;
1473
1474 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421475 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161476
1477 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421478 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161479
1480 response = trans->GetResponseInfo();
1481 EXPECT_FALSE(response == NULL);
1482 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1483
[email protected]71e4573a2009-05-21 22:03:001484 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161485 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1486 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1487
1488 TestCompletionCallback callback3;
1489
1490 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421491 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161492
1493 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421494 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161495
1496 response = trans->GetResponseInfo();
1497 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1498 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161499}
[email protected]4ddaf2502008-10-23 18:26:191500
[email protected]ea9dc9a2009-09-05 00:43:321501// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1502// can't hook into its internals to cause it to generate predictable NTLM
1503// authorization headers.
1504#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291505// The NTLM authentication unit tests were generated by capturing the HTTP
1506// requests and responses using Fiddler 2 and inspecting the generated random
1507// bytes in the debugger.
1508
1509// Enter the correct password and authenticate successfully.
1510TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421511 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201512 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591513 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401514 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431515 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241516
[email protected]1c773ea12009-04-28 19:58:421517 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241518 request.method = "GET";
1519 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1520 request.load_flags = 0;
1521
1522 MockWrite data_writes1[] = {
1523 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1524 "Host: 172.22.68.17\r\n"
1525 "Connection: keep-alive\r\n\r\n"),
1526 };
1527
1528 MockRead data_reads1[] = {
1529 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1530 // Negotiate and NTLM are often requested together. We only support NTLM.
1531 MockRead("WWW-Authenticate: Negotiate\r\n"),
1532 MockRead("WWW-Authenticate: NTLM\r\n"),
1533 MockRead("Connection: close\r\n"),
1534 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361535 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241536 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421537 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241538 };
1539
1540 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221541 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241542 // request we should be issuing -- the final header line contains a Type
1543 // 1 message.
1544 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1545 "Host: 172.22.68.17\r\n"
1546 "Connection: keep-alive\r\n"
1547 "Authorization: NTLM "
1548 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1549
1550 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1551 // (the credentials for the origin server). The second request continues
1552 // on the same connection.
1553 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1554 "Host: 172.22.68.17\r\n"
1555 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291556 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1557 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1558 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1559 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1560 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241561 };
1562
1563 MockRead data_reads2[] = {
1564 // The origin server responds with a Type 2 message.
1565 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1566 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291567 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241568 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1569 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1570 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1571 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1572 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1573 "BtAAAAAAA=\r\n"),
1574 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361575 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241576 MockRead("You are not authorized to view this page\r\n"),
1577
1578 // Lastly we get the desired content.
1579 MockRead("HTTP/1.1 200 OK\r\n"),
1580 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1581 MockRead("Content-Length: 13\r\n\r\n"),
1582 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421583 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241584 };
1585
[email protected]69b43fe2009-06-15 09:47:371586 StaticMockSocket data1(data_reads1, data_writes1);
1587 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:591588 session_deps.socket_factory.AddMockSocket(&data1);
1589 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]3f918782009-02-28 01:29:241590
1591 TestCompletionCallback callback1;
1592
[email protected]684970b2009-08-14 04:54:461593 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421594 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241595
1596 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421597 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241598
[email protected]0757e7702009-03-27 04:00:221599 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1600 TestCompletionCallback callback2;
1601 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421602 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221603 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421604 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221605 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1606
[email protected]1c773ea12009-04-28 19:58:421607 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241608 EXPECT_FALSE(response == NULL);
1609
1610 // The password prompt info should have been set in response->auth_challenge.
1611 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1612
[email protected]71e4573a2009-05-21 22:03:001613 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241614 EXPECT_EQ(L"", response->auth_challenge->realm);
1615 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1616
[email protected]0757e7702009-03-27 04:00:221617 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241618
[email protected]0757e7702009-03-27 04:00:221619 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421620 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241621
[email protected]0757e7702009-03-27 04:00:221622 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421623 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241624
1625 response = trans->GetResponseInfo();
1626 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1627 EXPECT_EQ(13, response->headers->GetContentLength());
1628}
1629
[email protected]385a4672009-03-11 22:21:291630// Enter a wrong password, and then the correct one.
1631TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421632 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201633 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591634 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401635 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431636 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291637
[email protected]1c773ea12009-04-28 19:58:421638 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291639 request.method = "GET";
1640 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1641 request.load_flags = 0;
1642
1643 MockWrite data_writes1[] = {
1644 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1645 "Host: 172.22.68.17\r\n"
1646 "Connection: keep-alive\r\n\r\n"),
1647 };
1648
1649 MockRead data_reads1[] = {
1650 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1651 // Negotiate and NTLM are often requested together. We only support NTLM.
1652 MockRead("WWW-Authenticate: Negotiate\r\n"),
1653 MockRead("WWW-Authenticate: NTLM\r\n"),
1654 MockRead("Connection: close\r\n"),
1655 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361656 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291657 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421658 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291659 };
1660
1661 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221662 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291663 // request we should be issuing -- the final header line contains a Type
1664 // 1 message.
1665 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1666 "Host: 172.22.68.17\r\n"
1667 "Connection: keep-alive\r\n"
1668 "Authorization: NTLM "
1669 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1670
1671 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1672 // (the credentials for the origin server). The second request continues
1673 // on the same connection.
1674 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1675 "Host: 172.22.68.17\r\n"
1676 "Connection: keep-alive\r\n"
1677 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1678 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1679 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1680 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1681 "4Ww7b7E=\r\n\r\n"),
1682 };
1683
1684 MockRead data_reads2[] = {
1685 // The origin server responds with a Type 2 message.
1686 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1687 MockRead("WWW-Authenticate: NTLM "
1688 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1689 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1690 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1691 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1692 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1693 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1694 "BtAAAAAAA=\r\n"),
1695 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361696 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291697 MockRead("You are not authorized to view this page\r\n"),
1698
1699 // Wrong password.
1700 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1701 MockRead("WWW-Authenticate: Negotiate\r\n"),
1702 MockRead("WWW-Authenticate: NTLM\r\n"),
1703 MockRead("Connection: close\r\n"),
1704 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361705 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291706 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421707 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291708 };
1709
1710 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221711 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291712 // request we should be issuing -- the final header line contains a Type
1713 // 1 message.
1714 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1715 "Host: 172.22.68.17\r\n"
1716 "Connection: keep-alive\r\n"
1717 "Authorization: NTLM "
1718 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1719
1720 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1721 // (the credentials for the origin server). The second request continues
1722 // on the same connection.
1723 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1724 "Host: 172.22.68.17\r\n"
1725 "Connection: keep-alive\r\n"
1726 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1727 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1728 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1729 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1730 "+4MUm7c=\r\n\r\n"),
1731 };
1732
1733 MockRead data_reads3[] = {
1734 // The origin server responds with a Type 2 message.
1735 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1736 MockRead("WWW-Authenticate: NTLM "
1737 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1738 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1739 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1740 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1741 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1742 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1743 "BtAAAAAAA=\r\n"),
1744 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361745 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291746 MockRead("You are not authorized to view this page\r\n"),
1747
1748 // Lastly we get the desired content.
1749 MockRead("HTTP/1.1 200 OK\r\n"),
1750 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1751 MockRead("Content-Length: 13\r\n\r\n"),
1752 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421753 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291754 };
1755
[email protected]69b43fe2009-06-15 09:47:371756 StaticMockSocket data1(data_reads1, data_writes1);
1757 StaticMockSocket data2(data_reads2, data_writes2);
1758 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:591759 session_deps.socket_factory.AddMockSocket(&data1);
1760 session_deps.socket_factory.AddMockSocket(&data2);
1761 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]385a4672009-03-11 22:21:291762
1763 TestCompletionCallback callback1;
1764
[email protected]684970b2009-08-14 04:54:461765 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421766 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291767
1768 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421769 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291770
[email protected]0757e7702009-03-27 04:00:221771 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291772 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221773 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421774 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291775 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421776 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221777 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291778
[email protected]1c773ea12009-04-28 19:58:421779 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291780 EXPECT_FALSE(response == NULL);
1781
1782 // The password prompt info should have been set in response->auth_challenge.
1783 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1784
[email protected]71e4573a2009-05-21 22:03:001785 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291786 EXPECT_EQ(L"", response->auth_challenge->realm);
1787 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1788
1789 TestCompletionCallback callback3;
1790
[email protected]0757e7702009-03-27 04:00:221791 // Enter the wrong password.
1792 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421793 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291794
1795 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421796 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291797
[email protected]0757e7702009-03-27 04:00:221798 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1799 TestCompletionCallback callback4;
1800 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421801 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221802 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421803 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221804 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1805
1806 response = trans->GetResponseInfo();
1807 EXPECT_FALSE(response == NULL);
1808
1809 // The password prompt info should have been set in response->auth_challenge.
1810 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1811
[email protected]71e4573a2009-05-21 22:03:001812 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221813 EXPECT_EQ(L"", response->auth_challenge->realm);
1814 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1815
1816 TestCompletionCallback callback5;
1817
1818 // Now enter the right password.
1819 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:421820 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221821
1822 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421823 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221824
[email protected]385a4672009-03-11 22:21:291825 response = trans->GetResponseInfo();
1826 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1827 EXPECT_EQ(13, response->headers->GetContentLength());
1828}
[email protected]ea9dc9a2009-09-05 00:43:321829#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:291830
[email protected]4ddaf2502008-10-23 18:26:191831// Test reading a server response which has only headers, and no body.
1832// After some maximum number of bytes is consumed, the transaction should
1833// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
1834TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:591835 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401836 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431837 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:191838
[email protected]1c773ea12009-04-28 19:58:421839 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:191840 request.method = "GET";
1841 request.url = GURL("http://www.google.com/");
1842 request.load_flags = 0;
1843
[email protected]b75b7b2f2009-10-06 00:54:531844 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:431845 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:531846 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:191847
1848 MockRead data_reads[] = {
1849 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:431850 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:191851 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:421852 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:191853 };
[email protected]69b43fe2009-06-15 09:47:371854 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591855 session_deps.socket_factory.AddMockSocket(&data);
[email protected]4ddaf2502008-10-23 18:26:191856
1857 TestCompletionCallback callback;
1858
[email protected]684970b2009-08-14 04:54:461859 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421860 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:191861
1862 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421863 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:191864
[email protected]1c773ea12009-04-28 19:58:421865 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:191866 EXPECT_TRUE(response == NULL);
1867}
[email protected]f4e426b2008-11-05 00:24:491868
1869// Make sure that we don't try to reuse a TCPClientSocket when failing to
1870// establish tunnel.
1871// http://code.google.com/p/chromium/issues/detail?id=3772
1872TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
1873 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591874 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011875
[email protected]228ff742009-06-05 01:19:591876 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:491877
[email protected]5695b8c2009-09-30 21:36:431878 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:491879
[email protected]1c773ea12009-04-28 19:58:421880 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:491881 request.method = "GET";
1882 request.url = GURL("https://www.google.com/");
1883 request.load_flags = 0;
1884
1885 // Since we have proxy, should try to establish tunnel.
1886 MockWrite data_writes1[] = {
1887 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451888 "Host: www.google.com\r\n"
1889 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:491890 };
1891
[email protected]77848d12008-11-14 00:00:221892 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:491893 // connection. Usually a proxy would return 501 (not implemented),
1894 // or 200 (tunnel established).
1895 MockRead data_reads1[] = {
1896 MockRead("HTTP/1.1 404 Not Found\r\n"),
1897 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421898 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:491899 };
1900
[email protected]69b43fe2009-06-15 09:47:371901 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:591902 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f4e426b2008-11-05 00:24:491903
1904 TestCompletionCallback callback1;
1905
[email protected]684970b2009-08-14 04:54:461906 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421907 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:491908
1909 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421910 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:491911
[email protected]1c773ea12009-04-28 19:58:421912 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:081913 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:491914
[email protected]b4404c02009-04-10 16:38:521915 // Empty the current queue. This is necessary because idle sockets are
1916 // added to the connection pool asynchronously with a PostTask.
1917 MessageLoop::current()->RunAllPending();
1918
[email protected]f4e426b2008-11-05 00:24:491919 // We now check to make sure the TCPClientSocket was not added back to
1920 // the pool.
[email protected]a937a06d2009-08-19 21:19:241921 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:491922 trans.reset();
[email protected]b4404c02009-04-10 16:38:521923 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:491924 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:241925 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:491926}
[email protected]372d34a2008-11-05 21:30:511927
[email protected]1b157c02009-04-21 01:55:401928// Make sure that we recycle a socket after reading all of the response body.
1929TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:591930 SessionDependencies session_deps;
1931 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:401932
[email protected]5695b8c2009-09-30 21:36:431933 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:401934
[email protected]1c773ea12009-04-28 19:58:421935 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:401936 request.method = "GET";
1937 request.url = GURL("http://www.google.com/");
1938 request.load_flags = 0;
1939
1940 MockRead data_reads[] = {
1941 // A part of the response body is received with the response headers.
1942 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
1943 // The rest of the response body is received in two parts.
1944 MockRead("lo"),
1945 MockRead(" world"),
1946 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421947 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:401948 };
1949
[email protected]69b43fe2009-06-15 09:47:371950 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591951 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1b157c02009-04-21 01:55:401952
1953 TestCompletionCallback callback;
1954
[email protected]684970b2009-08-14 04:54:461955 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421956 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:401957
1958 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421959 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401960
[email protected]1c773ea12009-04-28 19:58:421961 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:401962 EXPECT_TRUE(response != NULL);
1963
1964 EXPECT_TRUE(response->headers != NULL);
1965 std::string status_line = response->headers->GetStatusLine();
1966 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
1967
[email protected]a937a06d2009-08-19 21:19:241968 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:401969
1970 std::string response_data;
1971 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421972 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401973 EXPECT_EQ("hello world", response_data);
1974
1975 // Empty the current queue. This is necessary because idle sockets are
1976 // added to the connection pool asynchronously with a PostTask.
1977 MessageLoop::current()->RunAllPending();
1978
1979 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:241980 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:401981}
1982
[email protected]b4404c02009-04-10 16:38:521983// Make sure that we recycle a socket after a zero-length response.
1984// http://crbug.com/9880
1985TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:591986 SessionDependencies session_deps;
1987 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:521988
[email protected]5695b8c2009-09-30 21:36:431989 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:521990
[email protected]1c773ea12009-04-28 19:58:421991 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:521992 request.method = "GET";
1993 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
1994 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
1995 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
1996 "rt=prt.2642,ol.2649,xjs.2951");
1997 request.load_flags = 0;
1998
1999 MockRead data_reads[] = {
2000 MockRead("HTTP/1.1 204 No Content\r\n"
2001 "Content-Length: 0\r\n"
2002 "Content-Type: text/html\r\n\r\n"),
2003 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422004 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522005 };
2006
[email protected]69b43fe2009-06-15 09:47:372007 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:592008 session_deps.socket_factory.AddMockSocket(&data);
[email protected]b4404c02009-04-10 16:38:522009
2010 TestCompletionCallback callback;
2011
[email protected]684970b2009-08-14 04:54:462012 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422013 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522014
2015 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422016 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522017
[email protected]1c773ea12009-04-28 19:58:422018 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522019 EXPECT_TRUE(response != NULL);
2020
2021 EXPECT_TRUE(response->headers != NULL);
2022 std::string status_line = response->headers->GetStatusLine();
2023 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2024
[email protected]a937a06d2009-08-19 21:19:242025 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522026
2027 std::string response_data;
2028 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422029 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522030 EXPECT_EQ("", response_data);
2031
2032 // Empty the current queue. This is necessary because idle sockets are
2033 // added to the connection pool asynchronously with a PostTask.
2034 MessageLoop::current()->RunAllPending();
2035
2036 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242037 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522038}
2039
[email protected]372d34a2008-11-05 21:30:512040TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422041 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512042 // Transaction 1: a GET request that succeeds. The socket is recycled
2043 // after use.
2044 request[0].method = "GET";
2045 request[0].url = GURL("http://www.google.com/");
2046 request[0].load_flags = 0;
2047 // Transaction 2: a POST request. Reuses the socket kept alive from
2048 // transaction 1. The first attempts fails when writing the POST data.
2049 // This causes the transaction to retry with a new socket. The second
2050 // attempt succeeds.
2051 request[1].method = "POST";
2052 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422053 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512054 request[1].upload_data->AppendBytes("foo", 3);
2055 request[1].load_flags = 0;
2056
[email protected]228ff742009-06-05 01:19:592057 SessionDependencies session_deps;
2058 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512059
2060 // The first socket is used for transaction 1 and the first attempt of
2061 // transaction 2.
2062
2063 // The response of transaction 1.
2064 MockRead data_reads1[] = {
2065 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2066 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422067 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512068 };
2069 // The mock write results of transaction 1 and the first attempt of
2070 // transaction 2.
2071 MockWrite data_writes1[] = {
2072 MockWrite(false, 64), // GET
2073 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422074 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512075 };
[email protected]69b43fe2009-06-15 09:47:372076 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:512077
2078 // The second socket is used for the second attempt of transaction 2.
2079
2080 // The response of transaction 2.
2081 MockRead data_reads2[] = {
2082 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2083 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422084 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512085 };
2086 // The mock write results of the second attempt of transaction 2.
2087 MockWrite data_writes2[] = {
2088 MockWrite(false, 93), // POST
2089 MockWrite(false, 3), // POST data
2090 };
[email protected]69b43fe2009-06-15 09:47:372091 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:512092
[email protected]228ff742009-06-05 01:19:592093 session_deps.socket_factory.AddMockSocket(&data1);
2094 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]372d34a2008-11-05 21:30:512095
2096 const char* kExpectedResponseData[] = {
2097 "hello world", "welcome"
2098 };
2099
2100 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422101 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432102 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512103
2104 TestCompletionCallback callback;
2105
[email protected]684970b2009-08-14 04:54:462106 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422107 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512108
2109 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422110 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512111
[email protected]1c773ea12009-04-28 19:58:422112 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512113 EXPECT_TRUE(response != NULL);
2114
2115 EXPECT_TRUE(response->headers != NULL);
2116 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2117
2118 std::string response_data;
2119 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422120 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512121 EXPECT_EQ(kExpectedResponseData[i], response_data);
2122 }
2123}
[email protected]f9ee6b52008-11-08 06:46:232124
2125// Test the request-challenge-retry sequence for basic auth when there is
2126// an identity in the URL. The request should be sent as normal, but when
2127// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322128TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592129 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402130 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432131 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232132
[email protected]1c773ea12009-04-28 19:58:422133 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232134 request.method = "GET";
2135 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292136 request.url = GURL("http://foo:b@[email protected]/");
2137
2138 // The password contains an escaped character -- for this test to pass it
2139 // will need to be unescaped by HttpNetworkTransaction.
2140 EXPECT_EQ("b%40r", request.url.password());
2141
[email protected]ea9dc9a2009-09-05 00:43:322142 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232143
2144 MockWrite data_writes1[] = {
2145 MockWrite("GET / HTTP/1.1\r\n"
2146 "Host: www.google.com\r\n"
2147 "Connection: keep-alive\r\n\r\n"),
2148 };
2149
2150 MockRead data_reads1[] = {
2151 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2152 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2153 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422154 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232155 };
2156
2157 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322158 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232159 MockWrite data_writes2[] = {
2160 MockWrite("GET / HTTP/1.1\r\n"
2161 "Host: www.google.com\r\n"
2162 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292163 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232164 };
2165
2166 MockRead data_reads2[] = {
2167 MockRead("HTTP/1.0 200 OK\r\n"),
2168 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422169 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232170 };
2171
[email protected]69b43fe2009-06-15 09:47:372172 StaticMockSocket data1(data_reads1, data_writes1);
2173 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592174 session_deps.socket_factory.AddMockSocket(&data1);
2175 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232176
2177 TestCompletionCallback callback1;
2178
[email protected]684970b2009-08-14 04:54:462179 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422180 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232181
2182 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422183 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232184
[email protected]0757e7702009-03-27 04:00:222185 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2186 TestCompletionCallback callback2;
2187 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422188 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222189 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422190 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222191 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2192
[email protected]1c773ea12009-04-28 19:58:422193 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232194 EXPECT_FALSE(response == NULL);
2195
2196 // There is no challenge info, since the identity in URL worked.
2197 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2198
2199 EXPECT_EQ(100, response->headers->GetContentLength());
2200
2201 // Empty the current queue.
2202 MessageLoop::current()->RunAllPending();
2203}
2204
[email protected]ea9dc9a2009-09-05 00:43:322205// Test the request-challenge-retry sequence for basic auth when there is
2206// an incorrect identity in the URL. The identity from the URL should be used
2207// only once.
2208TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2209 SessionDependencies session_deps;
2210 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432211 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322212
2213 HttpRequestInfo request;
2214 request.method = "GET";
2215 // Note: the URL has a username:password in it. The password "baz" is
2216 // wrong (should be "bar").
2217 request.url = GURL("http://foo:[email protected]/");
2218
2219 request.load_flags = LOAD_NORMAL;
2220
2221 MockWrite data_writes1[] = {
2222 MockWrite("GET / HTTP/1.1\r\n"
2223 "Host: www.google.com\r\n"
2224 "Connection: keep-alive\r\n\r\n"),
2225 };
2226
2227 MockRead data_reads1[] = {
2228 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2229 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2230 MockRead("Content-Length: 10\r\n\r\n"),
2231 MockRead(false, ERR_FAILED),
2232 };
2233
2234 // After the challenge above, the transaction will be restarted using the
2235 // identity from the url (foo, baz) to answer the challenge.
2236 MockWrite data_writes2[] = {
2237 MockWrite("GET / HTTP/1.1\r\n"
2238 "Host: www.google.com\r\n"
2239 "Connection: keep-alive\r\n"
2240 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2241 };
2242
2243 MockRead data_reads2[] = {
2244 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2245 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2246 MockRead("Content-Length: 10\r\n\r\n"),
2247 MockRead(false, ERR_FAILED),
2248 };
2249
2250 // After the challenge above, the transaction will be restarted using the
2251 // identity supplied by the user (foo, bar) to answer the challenge.
2252 MockWrite data_writes3[] = {
2253 MockWrite("GET / HTTP/1.1\r\n"
2254 "Host: www.google.com\r\n"
2255 "Connection: keep-alive\r\n"
2256 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2257 };
2258
2259 MockRead data_reads3[] = {
2260 MockRead("HTTP/1.0 200 OK\r\n"),
2261 MockRead("Content-Length: 100\r\n\r\n"),
2262 MockRead(false, OK),
2263 };
2264
2265 StaticMockSocket data1(data_reads1, data_writes1);
2266 StaticMockSocket data2(data_reads2, data_writes2);
2267 StaticMockSocket data3(data_reads3, data_writes3);
2268 session_deps.socket_factory.AddMockSocket(&data1);
2269 session_deps.socket_factory.AddMockSocket(&data2);
2270 session_deps.socket_factory.AddMockSocket(&data3);
2271
2272 TestCompletionCallback callback1;
2273
2274 int rv = trans->Start(&request, &callback1, NULL);
2275 EXPECT_EQ(ERR_IO_PENDING, rv);
2276
2277 rv = callback1.WaitForResult();
2278 EXPECT_EQ(OK, rv);
2279
2280 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2281 TestCompletionCallback callback2;
2282 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2283 EXPECT_EQ(ERR_IO_PENDING, rv);
2284 rv = callback2.WaitForResult();
2285 EXPECT_EQ(OK, rv);
2286 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2287
2288 const HttpResponseInfo* response = trans->GetResponseInfo();
2289 EXPECT_FALSE(response == NULL);
2290 // The password prompt info should have been set in response->auth_challenge.
2291 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2292
2293 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2294 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2295 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2296
2297 TestCompletionCallback callback3;
2298 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2299 EXPECT_EQ(ERR_IO_PENDING, rv);
2300 rv = callback3.WaitForResult();
2301 EXPECT_EQ(OK, rv);
2302 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2303
2304 response = trans->GetResponseInfo();
2305 EXPECT_FALSE(response == NULL);
2306
2307 // There is no challenge info, since the identity worked.
2308 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2309
2310 EXPECT_EQ(100, response->headers->GetContentLength());
2311
2312 // Empty the current queue.
2313 MessageLoop::current()->RunAllPending();
2314}
2315
[email protected]f9ee6b52008-11-08 06:46:232316// Test that previously tried username/passwords for a realm get re-used.
2317TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592318 SessionDependencies session_deps;
2319 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232320
2321 // Transaction 1: authenticate (foo, bar) on MyRealm1
2322 {
[email protected]5695b8c2009-09-30 21:36:432323 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232324
[email protected]1c773ea12009-04-28 19:58:422325 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232326 request.method = "GET";
2327 request.url = GURL("http://www.google.com/x/y/z");
2328 request.load_flags = 0;
2329
2330 MockWrite data_writes1[] = {
2331 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2332 "Host: www.google.com\r\n"
2333 "Connection: keep-alive\r\n\r\n"),
2334 };
2335
2336 MockRead data_reads1[] = {
2337 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2338 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2339 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422340 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232341 };
2342
2343 // Resend with authorization (username=foo, password=bar)
2344 MockWrite data_writes2[] = {
2345 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2346 "Host: www.google.com\r\n"
2347 "Connection: keep-alive\r\n"
2348 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2349 };
2350
2351 // Sever accepts the authorization.
2352 MockRead data_reads2[] = {
2353 MockRead("HTTP/1.0 200 OK\r\n"),
2354 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422355 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232356 };
2357
[email protected]69b43fe2009-06-15 09:47:372358 StaticMockSocket data1(data_reads1, data_writes1);
2359 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592360 session_deps.socket_factory.AddMockSocket(&data1);
2361 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232362
2363 TestCompletionCallback callback1;
2364
[email protected]684970b2009-08-14 04:54:462365 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422366 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232367
2368 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422369 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232370
[email protected]1c773ea12009-04-28 19:58:422371 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232372 EXPECT_FALSE(response == NULL);
2373
2374 // The password prompt info should have been set in
2375 // response->auth_challenge.
2376 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2377
[email protected]71e4573a2009-05-21 22:03:002378 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232379 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2380 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2381
2382 TestCompletionCallback callback2;
2383
2384 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422385 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232386
2387 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422388 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232389
2390 response = trans->GetResponseInfo();
2391 EXPECT_FALSE(response == NULL);
2392 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2393 EXPECT_EQ(100, response->headers->GetContentLength());
2394 }
2395
2396 // ------------------------------------------------------------------------
2397
2398 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2399 {
[email protected]5695b8c2009-09-30 21:36:432400 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232401
[email protected]1c773ea12009-04-28 19:58:422402 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232403 request.method = "GET";
2404 // Note that Transaction 1 was at /x/y/z, so this is in the same
2405 // protection space as MyRealm1.
2406 request.url = GURL("http://www.google.com/x/y/a/b");
2407 request.load_flags = 0;
2408
2409 MockWrite data_writes1[] = {
2410 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2411 "Host: www.google.com\r\n"
2412 "Connection: keep-alive\r\n"
2413 // Send preemptive authorization for MyRealm1
2414 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2415 };
2416
2417 // The server didn't like the preemptive authorization, and
2418 // challenges us for a different realm (MyRealm2).
2419 MockRead data_reads1[] = {
2420 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2421 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2422 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422423 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232424 };
2425
2426 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2427 MockWrite data_writes2[] = {
2428 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2429 "Host: www.google.com\r\n"
2430 "Connection: keep-alive\r\n"
2431 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2432 };
2433
2434 // Sever accepts the authorization.
2435 MockRead data_reads2[] = {
2436 MockRead("HTTP/1.0 200 OK\r\n"),
2437 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422438 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232439 };
2440
[email protected]69b43fe2009-06-15 09:47:372441 StaticMockSocket data1(data_reads1, data_writes1);
2442 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592443 session_deps.socket_factory.AddMockSocket(&data1);
2444 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232445
2446 TestCompletionCallback callback1;
2447
[email protected]684970b2009-08-14 04:54:462448 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422449 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232450
2451 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422452 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232453
[email protected]1c773ea12009-04-28 19:58:422454 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232455 EXPECT_FALSE(response == NULL);
2456
2457 // The password prompt info should have been set in
2458 // response->auth_challenge.
2459 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2460
[email protected]71e4573a2009-05-21 22:03:002461 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232462 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2463 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2464
2465 TestCompletionCallback callback2;
2466
2467 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422468 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232469
2470 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422471 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232472
2473 response = trans->GetResponseInfo();
2474 EXPECT_FALSE(response == NULL);
2475 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2476 EXPECT_EQ(100, response->headers->GetContentLength());
2477 }
2478
2479 // ------------------------------------------------------------------------
2480
2481 // Transaction 3: Resend a request in MyRealm's protection space --
2482 // succeed with preemptive authorization.
2483 {
[email protected]5695b8c2009-09-30 21:36:432484 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232485
[email protected]1c773ea12009-04-28 19:58:422486 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232487 request.method = "GET";
2488 request.url = GURL("http://www.google.com/x/y/z2");
2489 request.load_flags = 0;
2490
2491 MockWrite data_writes1[] = {
2492 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2493 "Host: www.google.com\r\n"
2494 "Connection: keep-alive\r\n"
2495 // The authorization for MyRealm1 gets sent preemptively
2496 // (since the url is in the same protection space)
2497 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2498 };
2499
2500 // Sever accepts the preemptive authorization
2501 MockRead data_reads1[] = {
2502 MockRead("HTTP/1.0 200 OK\r\n"),
2503 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422504 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232505 };
2506
[email protected]69b43fe2009-06-15 09:47:372507 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:592508 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f9ee6b52008-11-08 06:46:232509
2510 TestCompletionCallback callback1;
2511
[email protected]684970b2009-08-14 04:54:462512 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422513 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232514
2515 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422516 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232517
[email protected]1c773ea12009-04-28 19:58:422518 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232519 EXPECT_FALSE(response == NULL);
2520
2521 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2522 EXPECT_EQ(100, response->headers->GetContentLength());
2523 }
2524
2525 // ------------------------------------------------------------------------
2526
2527 // Transaction 4: request another URL in MyRealm (however the
2528 // url is not known to belong to the protection space, so no pre-auth).
2529 {
[email protected]5695b8c2009-09-30 21:36:432530 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232531
[email protected]1c773ea12009-04-28 19:58:422532 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232533 request.method = "GET";
2534 request.url = GURL("http://www.google.com/x/1");
2535 request.load_flags = 0;
2536
2537 MockWrite data_writes1[] = {
2538 MockWrite("GET /x/1 HTTP/1.1\r\n"
2539 "Host: www.google.com\r\n"
2540 "Connection: keep-alive\r\n\r\n"),
2541 };
2542
2543 MockRead data_reads1[] = {
2544 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2545 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2546 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422547 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232548 };
2549
2550 // Resend with authorization from MyRealm's cache.
2551 MockWrite data_writes2[] = {
2552 MockWrite("GET /x/1 HTTP/1.1\r\n"
2553 "Host: www.google.com\r\n"
2554 "Connection: keep-alive\r\n"
2555 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2556 };
2557
2558 // Sever accepts the authorization.
2559 MockRead data_reads2[] = {
2560 MockRead("HTTP/1.0 200 OK\r\n"),
2561 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422562 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232563 };
2564
[email protected]69b43fe2009-06-15 09:47:372565 StaticMockSocket data1(data_reads1, data_writes1);
2566 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592567 session_deps.socket_factory.AddMockSocket(&data1);
2568 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232569
2570 TestCompletionCallback callback1;
2571
[email protected]684970b2009-08-14 04:54:462572 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422573 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232574
2575 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422576 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232577
[email protected]0757e7702009-03-27 04:00:222578 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2579 TestCompletionCallback callback2;
2580 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422581 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222582 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422583 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222584 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2585
[email protected]1c773ea12009-04-28 19:58:422586 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232587 EXPECT_FALSE(response == NULL);
2588 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2589 EXPECT_EQ(100, response->headers->GetContentLength());
2590 }
2591
2592 // ------------------------------------------------------------------------
2593
2594 // Transaction 5: request a URL in MyRealm, but the server rejects the
2595 // cached identity. Should invalidate and re-prompt.
2596 {
[email protected]5695b8c2009-09-30 21:36:432597 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232598
[email protected]1c773ea12009-04-28 19:58:422599 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232600 request.method = "GET";
2601 request.url = GURL("http://www.google.com/p/q/t");
2602 request.load_flags = 0;
2603
2604 MockWrite data_writes1[] = {
2605 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2606 "Host: www.google.com\r\n"
2607 "Connection: keep-alive\r\n\r\n"),
2608 };
2609
2610 MockRead data_reads1[] = {
2611 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2612 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2613 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422614 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232615 };
2616
2617 // Resend with authorization from cache for MyRealm.
2618 MockWrite data_writes2[] = {
2619 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2620 "Host: www.google.com\r\n"
2621 "Connection: keep-alive\r\n"
2622 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2623 };
2624
2625 // Sever rejects the authorization.
2626 MockRead data_reads2[] = {
2627 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2628 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2629 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422630 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232631 };
2632
2633 // At this point we should prompt for new credentials for MyRealm.
2634 // Restart with username=foo3, password=foo4.
2635 MockWrite data_writes3[] = {
2636 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2637 "Host: www.google.com\r\n"
2638 "Connection: keep-alive\r\n"
2639 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2640 };
2641
2642 // Sever accepts the authorization.
2643 MockRead data_reads3[] = {
2644 MockRead("HTTP/1.0 200 OK\r\n"),
2645 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422646 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232647 };
2648
[email protected]69b43fe2009-06-15 09:47:372649 StaticMockSocket data1(data_reads1, data_writes1);
2650 StaticMockSocket data2(data_reads2, data_writes2);
2651 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:592652 session_deps.socket_factory.AddMockSocket(&data1);
2653 session_deps.socket_factory.AddMockSocket(&data2);
2654 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]f9ee6b52008-11-08 06:46:232655
2656 TestCompletionCallback callback1;
2657
[email protected]684970b2009-08-14 04:54:462658 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422659 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232660
2661 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422662 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232663
[email protected]0757e7702009-03-27 04:00:222664 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2665 TestCompletionCallback callback2;
2666 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422667 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222668 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422669 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222670 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2671
[email protected]1c773ea12009-04-28 19:58:422672 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232673 EXPECT_FALSE(response == NULL);
2674
2675 // The password prompt info should have been set in
2676 // response->auth_challenge.
2677 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2678
[email protected]71e4573a2009-05-21 22:03:002679 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232680 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2681 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2682
[email protected]0757e7702009-03-27 04:00:222683 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232684
[email protected]0757e7702009-03-27 04:00:222685 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422686 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232687
[email protected]0757e7702009-03-27 04:00:222688 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422689 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232690
2691 response = trans->GetResponseInfo();
2692 EXPECT_FALSE(response == NULL);
2693 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2694 EXPECT_EQ(100, response->headers->GetContentLength());
2695 }
2696}
[email protected]89ceba9a2009-03-21 03:46:062697
2698// Test the ResetStateForRestart() private method.
2699TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2700 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592701 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402702 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432703 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062704
2705 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062706 trans->read_buf_ = new IOBuffer(15);
2707 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572708 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062709
2710 // Setup state in response_
[email protected]0877e3d2009-10-17 22:29:572711 trans->http_stream_.reset(new HttpBasicStream(NULL));
2712 HttpResponseInfo* response = trans->http_stream_->GetResponseInfo();
2713 response->auth_challenge = new AuthChallengeInfo();
2714 response->ssl_info.cert_status = -15;
2715 response->response_time = base::Time::Now();
2716 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062717
2718 { // Setup state for response_.vary_data
2719 HttpRequestInfo request;
2720 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2721 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:572722 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]89ceba9a2009-03-21 03:46:062723 request.extra_headers = "Foo: 1\nbar: 23";
[email protected]0877e3d2009-10-17 22:29:572724 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:062725 }
2726
2727 // Cause the above state to be reset.
2728 trans->ResetStateForRestart();
2729
2730 // Verify that the state that needed to be reset, has been reset.
[email protected]0877e3d2009-10-17 22:29:572731 response = trans->http_stream_->GetResponseInfo();
[email protected]9b6fee12009-09-29 18:13:072732 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:062733 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:572734 EXPECT_EQ(0U, trans->request_headers_.size());
2735 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2736 EXPECT_TRUE(response->headers.get() == NULL);
2737 EXPECT_EQ(false, response->was_cached);
2738 EXPECT_EQ(0, response->ssl_info.cert_status);
2739 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:062740}
2741
[email protected]bacff652009-03-31 17:50:332742// Test HTTPS connections to a site with a bad certificate
2743TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592744 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402745 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432746 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332747
2748 HttpRequestInfo request;
2749 request.method = "GET";
2750 request.url = GURL("https://www.google.com/");
2751 request.load_flags = 0;
2752
2753 MockWrite data_writes[] = {
2754 MockWrite("GET / HTTP/1.1\r\n"
2755 "Host: www.google.com\r\n"
2756 "Connection: keep-alive\r\n\r\n"),
2757 };
2758
2759 MockRead data_reads[] = {
2760 MockRead("HTTP/1.0 200 OK\r\n"),
2761 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2762 MockRead("Content-Length: 100\r\n\r\n"),
2763 MockRead(false, OK),
2764 };
2765
[email protected]69b43fe2009-06-15 09:47:372766 StaticMockSocket ssl_bad_certificate;
2767 StaticMockSocket data(data_reads, data_writes);
[email protected]bacff652009-03-31 17:50:332768 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2769 MockSSLSocket ssl(true, OK);
2770
[email protected]228ff742009-06-05 01:19:592771 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2772 session_deps.socket_factory.AddMockSocket(&data);
2773 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2774 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332775
2776 TestCompletionCallback callback;
2777
[email protected]684970b2009-08-14 04:54:462778 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332779 EXPECT_EQ(ERR_IO_PENDING, rv);
2780
2781 rv = callback.WaitForResult();
2782 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2783
2784 rv = trans->RestartIgnoringLastError(&callback);
2785 EXPECT_EQ(ERR_IO_PENDING, rv);
2786
2787 rv = callback.WaitForResult();
2788 EXPECT_EQ(OK, rv);
2789
2790 const HttpResponseInfo* response = trans->GetResponseInfo();
2791
2792 EXPECT_FALSE(response == NULL);
2793 EXPECT_EQ(100, response->headers->GetContentLength());
2794}
2795
2796// Test HTTPS connections to a site with a bad certificate, going through a
2797// proxy
2798TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592799 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332800
2801 HttpRequestInfo request;
2802 request.method = "GET";
2803 request.url = GURL("https://www.google.com/");
2804 request.load_flags = 0;
2805
2806 MockWrite proxy_writes[] = {
2807 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452808 "Host: www.google.com\r\n"
2809 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332810 };
2811
2812 MockRead proxy_reads[] = {
2813 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422814 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:332815 };
2816
2817 MockWrite data_writes[] = {
2818 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452819 "Host: www.google.com\r\n"
2820 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332821 MockWrite("GET / HTTP/1.1\r\n"
2822 "Host: www.google.com\r\n"
2823 "Connection: keep-alive\r\n\r\n"),
2824 };
2825
2826 MockRead data_reads[] = {
2827 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
2828 MockRead("HTTP/1.0 200 OK\r\n"),
2829 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2830 MockRead("Content-Length: 100\r\n\r\n"),
2831 MockRead(false, OK),
2832 };
2833
[email protected]69b43fe2009-06-15 09:47:372834 StaticMockSocket ssl_bad_certificate(proxy_reads, proxy_writes);
2835 StaticMockSocket data(data_reads, data_writes);
[email protected]bacff652009-03-31 17:50:332836 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2837 MockSSLSocket ssl(true, OK);
2838
[email protected]228ff742009-06-05 01:19:592839 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2840 session_deps.socket_factory.AddMockSocket(&data);
2841 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2842 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332843
2844 TestCompletionCallback callback;
2845
2846 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:592847 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:332848
[email protected]d207a5f2009-06-04 05:28:402849 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432850 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332851
[email protected]684970b2009-08-14 04:54:462852 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332853 EXPECT_EQ(ERR_IO_PENDING, rv);
2854
2855 rv = callback.WaitForResult();
2856 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2857
2858 rv = trans->RestartIgnoringLastError(&callback);
2859 EXPECT_EQ(ERR_IO_PENDING, rv);
2860
2861 rv = callback.WaitForResult();
2862 EXPECT_EQ(OK, rv);
2863
2864 const HttpResponseInfo* response = trans->GetResponseInfo();
2865
2866 EXPECT_FALSE(response == NULL);
2867 EXPECT_EQ(100, response->headers->GetContentLength());
2868 }
2869}
2870
[email protected]1c773ea12009-04-28 19:58:422871TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:592872 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402873 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432874 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:422875
2876 HttpRequestInfo request;
2877 request.method = "GET";
2878 request.url = GURL("http://www.google.com/");
2879 request.user_agent = "Chromium Ultra Awesome X Edition";
2880
2881 MockWrite data_writes[] = {
2882 MockWrite("GET / HTTP/1.1\r\n"
2883 "Host: www.google.com\r\n"
2884 "Connection: keep-alive\r\n"
2885 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
2886 };
2887
2888 // Lastly, the server responds with the actual content.
2889 MockRead data_reads[] = {
2890 MockRead("HTTP/1.0 200 OK\r\n"),
2891 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2892 MockRead("Content-Length: 100\r\n\r\n"),
2893 MockRead(false, OK),
2894 };
2895
[email protected]69b43fe2009-06-15 09:47:372896 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592897 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422898
2899 TestCompletionCallback callback;
2900
[email protected]684970b2009-08-14 04:54:462901 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422902 EXPECT_EQ(ERR_IO_PENDING, rv);
2903
2904 rv = callback.WaitForResult();
2905 EXPECT_EQ(OK, rv);
2906}
2907
2908TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:592909 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402910 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432911 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:422912
2913 HttpRequestInfo request;
2914 request.method = "GET";
2915 request.url = GURL("http://www.google.com/");
2916 request.load_flags = 0;
2917 request.referrer = GURL("http://the.previous.site.com/");
2918
2919 MockWrite data_writes[] = {
2920 MockWrite("GET / HTTP/1.1\r\n"
2921 "Host: www.google.com\r\n"
2922 "Connection: keep-alive\r\n"
2923 "Referer: http://the.previous.site.com/\r\n\r\n"),
2924 };
2925
2926 // Lastly, the server responds with the actual content.
2927 MockRead data_reads[] = {
2928 MockRead("HTTP/1.0 200 OK\r\n"),
2929 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2930 MockRead("Content-Length: 100\r\n\r\n"),
2931 MockRead(false, OK),
2932 };
2933
[email protected]69b43fe2009-06-15 09:47:372934 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592935 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422936
2937 TestCompletionCallback callback;
2938
[email protected]684970b2009-08-14 04:54:462939 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422940 EXPECT_EQ(ERR_IO_PENDING, rv);
2941
2942 rv = callback.WaitForResult();
2943 EXPECT_EQ(OK, rv);
2944}
2945
2946TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592947 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402948 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432949 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:422950
2951 HttpRequestInfo request;
2952 request.method = "POST";
2953 request.url = GURL("http://www.google.com/");
2954
2955 MockWrite data_writes[] = {
2956 MockWrite("POST / HTTP/1.1\r\n"
2957 "Host: www.google.com\r\n"
2958 "Connection: keep-alive\r\n"
2959 "Content-Length: 0\r\n\r\n"),
2960 };
2961
2962 // Lastly, the server responds with the actual content.
2963 MockRead data_reads[] = {
2964 MockRead("HTTP/1.0 200 OK\r\n"),
2965 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2966 MockRead("Content-Length: 100\r\n\r\n"),
2967 MockRead(false, OK),
2968 };
2969
[email protected]69b43fe2009-06-15 09:47:372970 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592971 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422972
2973 TestCompletionCallback callback;
2974
[email protected]684970b2009-08-14 04:54:462975 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422976 EXPECT_EQ(ERR_IO_PENDING, rv);
2977
2978 rv = callback.WaitForResult();
2979 EXPECT_EQ(OK, rv);
2980}
2981
2982TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592983 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402984 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432985 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:422986
2987 HttpRequestInfo request;
2988 request.method = "PUT";
2989 request.url = GURL("http://www.google.com/");
2990
2991 MockWrite data_writes[] = {
2992 MockWrite("PUT / HTTP/1.1\r\n"
2993 "Host: www.google.com\r\n"
2994 "Connection: keep-alive\r\n"
2995 "Content-Length: 0\r\n\r\n"),
2996 };
2997
2998 // Lastly, the server responds with the actual content.
2999 MockRead data_reads[] = {
3000 MockRead("HTTP/1.0 200 OK\r\n"),
3001 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3002 MockRead("Content-Length: 100\r\n\r\n"),
3003 MockRead(false, OK),
3004 };
3005
[email protected]69b43fe2009-06-15 09:47:373006 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593007 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423008
3009 TestCompletionCallback callback;
3010
[email protected]684970b2009-08-14 04:54:463011 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423012 EXPECT_EQ(ERR_IO_PENDING, rv);
3013
3014 rv = callback.WaitForResult();
3015 EXPECT_EQ(OK, rv);
3016}
3017
3018TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593019 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403020 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433021 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423022
3023 HttpRequestInfo request;
3024 request.method = "HEAD";
3025 request.url = GURL("http://www.google.com/");
3026
3027 MockWrite data_writes[] = {
3028 MockWrite("HEAD / HTTP/1.1\r\n"
3029 "Host: www.google.com\r\n"
3030 "Connection: keep-alive\r\n"
3031 "Content-Length: 0\r\n\r\n"),
3032 };
3033
3034 // Lastly, the server responds with the actual content.
3035 MockRead data_reads[] = {
3036 MockRead("HTTP/1.0 200 OK\r\n"),
3037 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3038 MockRead("Content-Length: 100\r\n\r\n"),
3039 MockRead(false, OK),
3040 };
3041
[email protected]69b43fe2009-06-15 09:47:373042 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593043 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423044
3045 TestCompletionCallback callback;
3046
[email protected]684970b2009-08-14 04:54:463047 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423048 EXPECT_EQ(ERR_IO_PENDING, rv);
3049
3050 rv = callback.WaitForResult();
3051 EXPECT_EQ(OK, rv);
3052}
3053
3054TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593055 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403056 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433057 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423058
3059 HttpRequestInfo request;
3060 request.method = "GET";
3061 request.url = GURL("http://www.google.com/");
3062 request.load_flags = LOAD_BYPASS_CACHE;
3063
3064 MockWrite data_writes[] = {
3065 MockWrite("GET / HTTP/1.1\r\n"
3066 "Host: www.google.com\r\n"
3067 "Connection: keep-alive\r\n"
3068 "Pragma: no-cache\r\n"
3069 "Cache-Control: no-cache\r\n\r\n"),
3070 };
3071
3072 // Lastly, the server responds with the actual content.
3073 MockRead data_reads[] = {
3074 MockRead("HTTP/1.0 200 OK\r\n"),
3075 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3076 MockRead("Content-Length: 100\r\n\r\n"),
3077 MockRead(false, OK),
3078 };
3079
[email protected]69b43fe2009-06-15 09:47:373080 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593081 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423082
3083 TestCompletionCallback callback;
3084
[email protected]684970b2009-08-14 04:54:463085 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423086 EXPECT_EQ(ERR_IO_PENDING, rv);
3087
3088 rv = callback.WaitForResult();
3089 EXPECT_EQ(OK, rv);
3090}
3091
3092TEST_F(HttpNetworkTransactionTest,
3093 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593094 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403095 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433096 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423097
3098 HttpRequestInfo request;
3099 request.method = "GET";
3100 request.url = GURL("http://www.google.com/");
3101 request.load_flags = LOAD_VALIDATE_CACHE;
3102
3103 MockWrite data_writes[] = {
3104 MockWrite("GET / HTTP/1.1\r\n"
3105 "Host: www.google.com\r\n"
3106 "Connection: keep-alive\r\n"
3107 "Cache-Control: max-age=0\r\n\r\n"),
3108 };
3109
3110 // Lastly, the server responds with the actual content.
3111 MockRead data_reads[] = {
3112 MockRead("HTTP/1.0 200 OK\r\n"),
3113 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3114 MockRead("Content-Length: 100\r\n\r\n"),
3115 MockRead(false, OK),
3116 };
3117
[email protected]69b43fe2009-06-15 09:47:373118 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593119 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423120
3121 TestCompletionCallback callback;
3122
[email protected]684970b2009-08-14 04:54:463123 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423124 EXPECT_EQ(ERR_IO_PENDING, rv);
3125
3126 rv = callback.WaitForResult();
3127 EXPECT_EQ(OK, rv);
3128}
3129
3130TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593131 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403132 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433133 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423134
3135 HttpRequestInfo request;
3136 request.method = "GET";
3137 request.url = GURL("http://www.google.com/");
3138 request.extra_headers = "FooHeader: Bar\r\n";
3139
3140 MockWrite data_writes[] = {
3141 MockWrite("GET / HTTP/1.1\r\n"
3142 "Host: www.google.com\r\n"
3143 "Connection: keep-alive\r\n"
3144 "FooHeader: Bar\r\n\r\n"),
3145 };
3146
3147 // Lastly, the server responds with the actual content.
3148 MockRead data_reads[] = {
3149 MockRead("HTTP/1.0 200 OK\r\n"),
3150 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3151 MockRead("Content-Length: 100\r\n\r\n"),
3152 MockRead(false, OK),
3153 };
3154
[email protected]69b43fe2009-06-15 09:47:373155 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593156 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423157
3158 TestCompletionCallback callback;
3159
[email protected]684970b2009-08-14 04:54:463160 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423161 EXPECT_EQ(ERR_IO_PENDING, rv);
3162
3163 rv = callback.WaitForResult();
3164 EXPECT_EQ(OK, rv);
3165}
3166
[email protected]3cd17242009-06-23 02:59:023167TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093168 SessionDependencies session_deps(
3169 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023170
3171 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433172 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023173
3174 HttpRequestInfo request;
3175 request.method = "GET";
3176 request.url = GURL("http://www.google.com/");
3177 request.load_flags = 0;
3178
3179 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3180 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3181
3182 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353183 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023184 MockWrite("GET / HTTP/1.1\r\n"
3185 "Host: www.google.com\r\n"
3186 "Connection: keep-alive\r\n\r\n")
3187 };
3188
3189 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353190 MockWrite(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023191 MockRead("HTTP/1.0 200 OK\r\n"),
3192 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3193 MockRead("Payload"),
3194 MockRead(false, OK)
3195 };
3196
3197 StaticMockSocket data(data_reads, data_writes);
3198 session_deps.socket_factory.AddMockSocket(&data);
3199
3200 TestCompletionCallback callback;
3201
[email protected]684970b2009-08-14 04:54:463202 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023203 EXPECT_EQ(ERR_IO_PENDING, rv);
3204
3205 rv = callback.WaitForResult();
3206 EXPECT_EQ(OK, rv);
3207
3208 const HttpResponseInfo* response = trans->GetResponseInfo();
3209 EXPECT_FALSE(response == NULL);
3210
3211 std::string response_text;
3212 rv = ReadTransaction(trans.get(), &response_text);
3213 EXPECT_EQ(OK, rv);
3214 EXPECT_EQ("Payload", response_text);
3215}
3216
3217TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093218 SessionDependencies session_deps(
3219 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023220
3221 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433222 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023223
3224 HttpRequestInfo request;
3225 request.method = "GET";
3226 request.url = GURL("https://www.google.com/");
3227 request.load_flags = 0;
3228
3229 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3230 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3231
3232 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353233 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3234 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023235 MockWrite("GET / HTTP/1.1\r\n"
3236 "Host: www.google.com\r\n"
3237 "Connection: keep-alive\r\n\r\n")
3238 };
3239
3240 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353241 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3242 arraysize(read_buffer)),
3243 MockRead("HTTP/1.0 200 OK\r\n"),
3244 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3245 MockRead("Payload"),
3246 MockRead(false, OK)
3247 };
3248
3249 StaticMockSocket data(data_reads, data_writes);
3250 session_deps.socket_factory.AddMockSocket(&data);
3251
3252 MockSSLSocket ssl(true, OK);
3253 session_deps.socket_factory.AddMockSSLSocket(&ssl);
3254
3255 TestCompletionCallback callback;
3256
[email protected]684970b2009-08-14 04:54:463257 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353258 EXPECT_EQ(ERR_IO_PENDING, rv);
3259
3260 rv = callback.WaitForResult();
3261 EXPECT_EQ(OK, rv);
3262
3263 const HttpResponseInfo* response = trans->GetResponseInfo();
3264 EXPECT_FALSE(response == NULL);
3265
3266 std::string response_text;
3267 rv = ReadTransaction(trans.get(), &response_text);
3268 EXPECT_EQ(OK, rv);
3269 EXPECT_EQ("Payload", response_text);
3270}
3271
3272TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093273 SessionDependencies session_deps(
3274 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353275
3276 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433277 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353278
3279 HttpRequestInfo request;
3280 request.method = "GET";
3281 request.url = GURL("http://www.google.com/");
3282 request.load_flags = 0;
3283
3284 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3285 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3286 const char kSOCKS5OkRequest[] =
3287 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3288 const char kSOCKS5OkResponse[] =
3289 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3290
3291 MockWrite data_writes[] = {
3292 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3293 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3294 MockWrite("GET / HTTP/1.1\r\n"
3295 "Host: www.google.com\r\n"
3296 "Connection: keep-alive\r\n\r\n")
3297 };
3298
3299 MockRead data_reads[] = {
3300 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3301 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3302 MockRead("HTTP/1.0 200 OK\r\n"),
3303 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3304 MockRead("Payload"),
3305 MockRead(false, OK)
3306 };
3307
3308 StaticMockSocket data(data_reads, data_writes);
3309 session_deps.socket_factory.AddMockSocket(&data);
3310
3311 TestCompletionCallback callback;
3312
[email protected]684970b2009-08-14 04:54:463313 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353314 EXPECT_EQ(ERR_IO_PENDING, rv);
3315
3316 rv = callback.WaitForResult();
3317 EXPECT_EQ(OK, rv);
3318
3319 const HttpResponseInfo* response = trans->GetResponseInfo();
3320 EXPECT_FALSE(response == NULL);
3321
3322 std::string response_text;
3323 rv = ReadTransaction(trans.get(), &response_text);
3324 EXPECT_EQ(OK, rv);
3325 EXPECT_EQ("Payload", response_text);
3326}
3327
3328TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093329 SessionDependencies session_deps(
3330 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353331
3332 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433333 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353334
3335 HttpRequestInfo request;
3336 request.method = "GET";
3337 request.url = GURL("https://www.google.com/");
3338 request.load_flags = 0;
3339
3340 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3341 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3342 const unsigned char kSOCKS5OkRequest[] =
3343 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x01, 0xBB };
3344 const char kSOCKS5OkResponse[] =
3345 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3346
3347 MockWrite data_writes[] = {
3348 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3349 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3350 arraysize(kSOCKS5OkRequest)),
3351 MockWrite("GET / HTTP/1.1\r\n"
3352 "Host: www.google.com\r\n"
3353 "Connection: keep-alive\r\n\r\n")
3354 };
3355
3356 MockRead data_reads[] = {
3357 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3358 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023359 MockRead("HTTP/1.0 200 OK\r\n"),
3360 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3361 MockRead("Payload"),
3362 MockRead(false, OK)
3363 };
3364
3365 StaticMockSocket data(data_reads, data_writes);
3366 session_deps.socket_factory.AddMockSocket(&data);
3367
3368 MockSSLSocket ssl(true, OK);
3369 session_deps.socket_factory.AddMockSSLSocket(&ssl);
3370
3371 TestCompletionCallback callback;
3372
[email protected]684970b2009-08-14 04:54:463373 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023374 EXPECT_EQ(ERR_IO_PENDING, rv);
3375
3376 rv = callback.WaitForResult();
3377 EXPECT_EQ(OK, rv);
3378
3379 const HttpResponseInfo* response = trans->GetResponseInfo();
3380 EXPECT_FALSE(response == NULL);
3381
3382 std::string response_text;
3383 rv = ReadTransaction(trans.get(), &response_text);
3384 EXPECT_EQ(OK, rv);
3385 EXPECT_EQ("Payload", response_text);
3386}
3387
[email protected]04e5be32009-06-26 20:00:313388// Tests that for connection endpoints the group names are correctly set.
3389TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3390 const struct {
3391 const std::string proxy_server;
3392 const std::string url;
3393 const std::string expected_group_name;
3394 } tests[] = {
3395 {
3396 "", // no proxy (direct)
3397 "http://www.google.com/direct",
3398 "http://www.google.com/",
3399 },
3400 {
3401 "http_proxy",
3402 "http://www.google.com/http_proxy_normal",
3403 "proxy/http_proxy:80/",
3404 },
3405 {
3406 "socks4://socks_proxy:1080",
3407 "http://www.google.com/socks4_direct",
3408 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3409 },
3410
3411 // SSL Tests
3412 {
3413 "",
3414 "https://www.google.com/direct_ssl",
3415 "https://www.google.com/",
3416 },
3417 {
3418 "http_proxy",
3419 "https://www.google.com/http_connect_ssl",
3420 "proxy/http_proxy:80/https://www.google.com/",
3421 },
3422 {
3423 "socks4://socks_proxy:1080",
3424 "https://www.google.com/socks4_ssl",
3425 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3426 },
3427 };
3428
3429 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093430 SessionDependencies session_deps(
3431 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313432
3433 scoped_refptr<CaptureGroupNameSocketPool> conn_pool(
3434 new CaptureGroupNameSocketPool());
3435
3436 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a937a06d2009-08-19 21:19:243437 session->tcp_socket_pool_ = conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313438
[email protected]5695b8c2009-09-30 21:36:433439 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313440
3441 HttpRequestInfo request;
3442 request.method = "GET";
3443 request.url = GURL(tests[i].url);
3444 request.load_flags = 0;
3445
3446 TestCompletionCallback callback;
3447
3448 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463449 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]04e5be32009-06-26 20:00:313450 EXPECT_EQ(tests[i].expected_group_name,
3451 conn_pool->last_group_name_received());
3452 }
3453}
3454
[email protected]9172a982009-06-06 00:30:253455TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543456 SessionDependencies session_deps(
3457 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323458
3459 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3460
[email protected]9172a982009-06-06 00:30:253461 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433462 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253463
3464 HttpRequestInfo request;
3465 request.method = "GET";
3466 request.url = GURL("http://www.google.com/");
3467
3468 TestCompletionCallback callback;
3469
[email protected]684970b2009-08-14 04:54:463470 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253471 EXPECT_EQ(ERR_IO_PENDING, rv);
3472
[email protected]9172a982009-06-06 00:30:253473 rv = callback.WaitForResult();
3474 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3475}
3476
[email protected]f3e6c1e2009-06-15 20:52:123477// Host resolution observer used by
3478// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3479// resovle requests are issued with a referrer of |expected_referrer|.
3480class ResolutionReferrerObserver : public HostResolver::Observer {
3481 public:
3482 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3483 : expected_referrer_(expected_referrer),
3484 called_start_with_referrer_(false),
3485 called_finish_with_referrer_(false) {
3486 }
3487
3488 virtual void OnStartResolution(int id,
3489 const HostResolver::RequestInfo& info) {
3490 if (info.referrer() == expected_referrer_)
3491 called_start_with_referrer_ = true;
3492 }
3493
3494 virtual void OnFinishResolutionWithStatus(
3495 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3496 if (info.referrer() == expected_referrer_)
3497 called_finish_with_referrer_ = true;
3498 }
3499
[email protected]eb255d32009-06-17 02:11:033500 virtual void OnCancelResolution(int id,
3501 const HostResolver::RequestInfo& info ) {
3502 FAIL() << "Should not be cancelling any requests!";
3503 }
3504
[email protected]f3e6c1e2009-06-15 20:52:123505 bool did_complete_with_expected_referrer() const {
3506 return called_start_with_referrer_ && called_finish_with_referrer_;
3507 }
3508
3509 private:
3510 GURL expected_referrer_;
3511 bool called_start_with_referrer_;
3512 bool called_finish_with_referrer_;
3513
3514 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3515};
3516
3517// Make sure that when HostResolver::Resolve() is invoked, it passes through
3518// the "referrer". This is depended on by the DNS prefetch observer.
3519TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3520 GURL referrer = GURL("http://expected-referrer/");
3521 EXPECT_TRUE(referrer.is_valid());
3522 ResolutionReferrerObserver resolution_observer(referrer);
3523
3524 SessionDependencies session_deps;
3525 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433526 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123527
3528 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143529 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123530
3531 // Connect up a mock socket which will fail when reading.
3532 MockRead data_reads[] = {
3533 MockRead(false, ERR_FAILED),
3534 };
3535 StaticMockSocket data(data_reads, NULL);
3536 session_deps.socket_factory.AddMockSocket(&data);
3537
3538 // Issue a request, containing an HTTP referrer.
3539 HttpRequestInfo request;
3540 request.method = "GET";
3541 request.referrer = referrer;
3542 request.url = GURL("http://www.google.com/");
3543
3544 // Run the request until it fails reading from the socket.
3545 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463546 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123547 EXPECT_EQ(ERR_IO_PENDING, rv);
3548 rv = callback.WaitForResult();
3549 EXPECT_EQ(ERR_FAILED, rv);
3550
3551 // Check that the host resolution observer saw |referrer|.
3552 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3553}
3554
[email protected]3b9cca42009-06-16 01:08:283555// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3556// host cache is bypassed.
3557TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3558 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323559
[email protected]a2c2fb92009-07-18 07:31:043560 // Select a host resolver that does caching.
3561 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323562
[email protected]3b9cca42009-06-16 01:08:283563 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433564 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:283565
3566 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3567 // a synchronous lookup.)
3568 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143569 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463570 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3571 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283572 EXPECT_EQ(OK, rv);
3573
3574 // Verify that it was added to host cache, by doing a subsequent async lookup
3575 // and confirming it completes synchronously.
3576 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463577 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283578 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463579 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323580 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283581
3582 // Inject a failure the next time that "www.google.com" is resolved. This way
3583 // we can tell if the next lookup hit the cache, or the "network".
3584 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323585 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283586
3587 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3588 // first read -- this won't be reached as the host resolution will fail first.
3589 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
3590 StaticMockSocket data(data_reads, NULL);
3591 session_deps.socket_factory.AddMockSocket(&data);
3592
3593 // Issue a request, asking to bypass the cache(s).
3594 HttpRequestInfo request;
3595 request.method = "GET";
3596 request.load_flags = LOAD_BYPASS_CACHE;
3597 request.url = GURL("http://www.google.com/");
3598
3599 // Run the request.
3600 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463601 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283602 ASSERT_EQ(ERR_IO_PENDING, rv);
3603 rv = callback.WaitForResult();
3604
3605 // If we bypassed the cache, we would have gotten a failure while resolving
3606 // "www.google.com".
3607 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3608}
3609
[email protected]0877e3d2009-10-17 22:29:573610// Make sure we can handle an error when writing the request.
3611TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3612 SessionDependencies session_deps;
3613 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3614
3615 HttpRequestInfo request;
3616 request.method = "GET";
3617 request.url = GURL("http://www.foo.com/");
3618 request.load_flags = 0;
3619
3620 MockWrite write_failure[] = {
3621 MockWrite(true, ERR_CONNECTION_RESET),
3622 };
3623 StaticMockSocket data(NULL, write_failure);
3624 session_deps.socket_factory.AddMockSocket(&data);
3625
3626 TestCompletionCallback callback;
3627
3628 scoped_ptr<HttpTransaction> trans(
3629 new HttpNetworkTransaction(CreateSession(&session_deps)));
3630
3631 int rv = trans->Start(&request, &callback, NULL);
3632 EXPECT_EQ(ERR_IO_PENDING, rv);
3633
3634 rv = callback.WaitForResult();
3635 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3636}
3637
3638// Check that a connection closed after the start of the headers finishes ok.
3639TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3640 SessionDependencies session_deps;
3641 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3642
3643 HttpRequestInfo request;
3644 request.method = "GET";
3645 request.url = GURL("http://www.foo.com/");
3646 request.load_flags = 0;
3647
3648 MockRead data_reads[] = {
3649 MockRead("HTTP/1."),
3650 MockRead(false, OK),
3651 };
3652
3653 StaticMockSocket data(data_reads, NULL);
3654 session_deps.socket_factory.AddMockSocket(&data);
3655
3656 TestCompletionCallback callback;
3657
3658 scoped_ptr<HttpTransaction> trans(
3659 new HttpNetworkTransaction(CreateSession(&session_deps)));
3660
3661 int rv = trans->Start(&request, &callback, NULL);
3662 EXPECT_EQ(ERR_IO_PENDING, rv);
3663
3664 rv = callback.WaitForResult();
3665 EXPECT_EQ(OK, rv);
3666
3667 const HttpResponseInfo* response = trans->GetResponseInfo();
3668 EXPECT_TRUE(response != NULL);
3669
3670 EXPECT_TRUE(response->headers != NULL);
3671 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
3672
3673 std::string response_data;
3674 rv = ReadTransaction(trans.get(), &response_data);
3675 EXPECT_EQ(OK, rv);
3676 EXPECT_EQ("", response_data);
3677}
3678
3679// Make sure that a dropped connection while draining the body for auth
3680// restart does the right thing.
3681TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
3682 SessionDependencies session_deps;
3683 scoped_ptr<HttpTransaction> trans(
3684 new HttpNetworkTransaction(CreateSession(&session_deps)));
3685
3686 HttpRequestInfo request;
3687 request.method = "GET";
3688 request.url = GURL("http://www.google.com/");
3689 request.load_flags = 0;
3690
3691 MockWrite data_writes1[] = {
3692 MockWrite("GET / HTTP/1.1\r\n"
3693 "Host: www.google.com\r\n"
3694 "Connection: keep-alive\r\n\r\n"),
3695 };
3696
3697 MockRead data_reads1[] = {
3698 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3699 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3700 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3701 MockRead("Content-Length: 14\r\n\r\n"),
3702 MockRead("Unauth"),
3703 MockRead(true, ERR_CONNECTION_RESET),
3704 };
3705
3706 StaticMockSocket data1(data_reads1, data_writes1);
3707 session_deps.socket_factory.AddMockSocket(&data1);
3708
3709 // After calling trans->RestartWithAuth(), this is the request we should
3710 // be issuing -- the final header line contains the credentials.
3711 MockWrite data_writes2[] = {
3712 MockWrite("GET / HTTP/1.1\r\n"
3713 "Host: www.google.com\r\n"
3714 "Connection: keep-alive\r\n"
3715 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3716 };
3717
3718 // Lastly, the server responds with the actual content.
3719 MockRead data_reads2[] = {
3720 MockRead("HTTP/1.1 200 OK\r\n"),
3721 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3722 MockRead("Content-Length: 100\r\n\r\n"),
3723 MockRead(false, OK),
3724 };
3725
3726 StaticMockSocket data2(data_reads2, data_writes2);
3727 session_deps.socket_factory.AddMockSocket(&data2);
3728
3729 TestCompletionCallback callback1;
3730
3731 int rv = trans->Start(&request, &callback1, NULL);
3732 EXPECT_EQ(ERR_IO_PENDING, rv);
3733
3734 rv = callback1.WaitForResult();
3735 EXPECT_EQ(OK, rv);
3736
3737 const HttpResponseInfo* response = trans->GetResponseInfo();
3738 EXPECT_FALSE(response == NULL);
3739
3740 // The password prompt info should have been set in response->auth_challenge.
3741 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3742
3743 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3744 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3745 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3746
3747 TestCompletionCallback callback2;
3748
3749 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3750 EXPECT_EQ(ERR_IO_PENDING, rv);
3751
3752 rv = callback2.WaitForResult();
3753 EXPECT_EQ(OK, rv);
3754
3755 response = trans->GetResponseInfo();
3756 EXPECT_FALSE(response == NULL);
3757 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3758 EXPECT_EQ(100, response->headers->GetContentLength());
3759}
3760
3761// Test HTTPS connections going through a proxy that sends extra data.
3762TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
3763 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
3764
3765 HttpRequestInfo request;
3766 request.method = "GET";
3767 request.url = GURL("https://www.google.com/");
3768 request.load_flags = 0;
3769
3770 MockRead proxy_reads[] = {
3771 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
3772 MockRead(false, OK)
3773 };
3774
3775 StaticMockSocket data(proxy_reads, NULL);
3776 MockSSLSocket ssl(true, OK);
3777
3778 session_deps.socket_factory.AddMockSocket(&data);
3779 session_deps.socket_factory.AddMockSSLSocket(&ssl);
3780
3781 TestCompletionCallback callback;
3782
3783 session_deps.socket_factory.ResetNextMockIndexes();
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_TUNNEL_CONNECTION_FAILED, rv);
3793}
3794
[email protected]89ceba9a2009-03-21 03:46:063795} // namespace net