blob: b47e34ad5c8a44968fd3b2139a1063dcbeb94274 [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]385a4672009-03-11 22:21:2914#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5715#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5216#include "net/http/http_network_session.h"
17#include "net/http/http_network_transaction.h"
[email protected]0877e3d2009-10-17 22:29:5718#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5219#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5320#include "net/proxy/proxy_config_service_fixed.h"
[email protected]f7984fc62009-06-22 23:26:4421#include "net/socket/client_socket_factory.h"
22#include "net/socket/socket_test_util.h"
23#include "net/socket/ssl_client_socket.h"
initial.commit586acc5fe2008-07-26 22:42:5224#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1525#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5226
27//-----------------------------------------------------------------------------
28
[email protected]89ceba9a2009-03-21 03:46:0629namespace net {
30
[email protected]db8f44c2008-12-13 04:52:0131// Create a proxy service which fails on all requests (falls back to direct).
[email protected]1c773ea12009-04-28 19:58:4232ProxyService* CreateNullProxyService() {
33 return ProxyService::CreateNull();
initial.commit586acc5fe2008-07-26 22:42:5234}
35
[email protected]e44de5d2009-06-05 20:12:4536// Helper to manage the lifetimes of the dependencies for a
37// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5938class SessionDependencies {
39 public:
40 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4241 SessionDependencies()
42 : host_resolver(new MockHostResolver),
43 proxy_service(CreateNullProxyService()),
44 ssl_config_service(new SSLConfigServiceDefaults) {}
[email protected]228ff742009-06-05 01:19:5945
46 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4547 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4248 : host_resolver(new MockHostResolver),
49 proxy_service(proxy_service),
50 ssl_config_service(new SSLConfigServiceDefaults) {}
[email protected]228ff742009-06-05 01:19:5951
[email protected]a2c2fb92009-07-18 07:31:0452 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0953 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4254 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5955 MockClientSocketFactory socket_factory;
56};
57
[email protected]1c773ea12009-04-28 19:58:4258ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5059 net::ProxyConfig proxy_config;
60 proxy_config.proxy_rules.ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3961 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5362}
63
64
[email protected]228ff742009-06-05 01:19:5965HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]94a0d3d92009-06-27 01:50:1466 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:0967 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:4268 &session_deps->socket_factory,
69 session_deps->ssl_config_service);
[email protected]e8d536192008-10-17 22:21:1470}
71
[email protected]89836e22008-09-25 20:33:4272class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:5273 public:
[email protected]0e75a732008-10-16 20:36:0974 virtual void TearDown() {
75 // Empty the current queue.
76 MessageLoop::current()->RunAllPending();
77 PlatformTest::TearDown();
78 }
79
[email protected]3d2a59b2008-09-26 19:44:2580 protected:
81 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:5282
[email protected]ff007e162009-05-23 09:13:1583 struct SimpleGetHelperResult {
84 int rv;
85 std::string status_line;
86 std::string response_data;
87 };
initial.commit586acc5fe2008-07-26 22:42:5288
[email protected]ff007e162009-05-23 09:13:1589 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
90 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:5291
[email protected]228ff742009-06-05 01:19:5992 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:4093 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:4394 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:5295
[email protected]ff007e162009-05-23 09:13:1596 HttpRequestInfo request;
97 request.method = "GET";
98 request.url = GURL("http://www.google.com/");
99 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52100
[email protected]69b43fe2009-06-15 09:47:37101 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59102 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52103
[email protected]ff007e162009-05-23 09:13:15104 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52105
[email protected]684970b2009-08-14 04:54:46106 int rv = trans->Start(&request, &callback, NULL);
[email protected]ff007e162009-05-23 09:13:15107 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52108
[email protected]ff007e162009-05-23 09:13:15109 out.rv = callback.WaitForResult();
110 if (out.rv != OK)
111 return out;
112
113 const HttpResponseInfo* response = trans->GetResponseInfo();
114 EXPECT_TRUE(response != NULL);
115
116 EXPECT_TRUE(response->headers != NULL);
117 out.status_line = response->headers->GetStatusLine();
118
119 rv = ReadTransaction(trans.get(), &out.response_data);
120 EXPECT_EQ(OK, rv);
121
[email protected]aecfbf22008-10-16 02:02:47122 return out;
[email protected]ff007e162009-05-23 09:13:15123 }
initial.commit586acc5fe2008-07-26 22:42:52124
[email protected]ff007e162009-05-23 09:13:15125 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
126 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52127
[email protected]ff007e162009-05-23 09:13:15128 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15129};
[email protected]231d5a32008-09-13 00:45:27130
[email protected]15a5ccf82008-10-23 19:57:43131// Fill |str| with a long header list that consumes >= |size| bytes.
132void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19133 const char* row =
134 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
135 const int sizeof_row = strlen(row);
136 const int num_rows = static_cast<int>(
137 ceil(static_cast<float>(size) / sizeof_row));
138 const int sizeof_data = num_rows * sizeof_row;
139 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43140 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51141
[email protected]4ddaf2502008-10-23 18:26:19142 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43143 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19144}
145
[email protected]385a4672009-03-11 22:21:29146// Alternative functions that eliminate randomness and dependency on the local
147// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20148void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29149 static const uint8 bytes[] = {
150 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
151 };
152 static size_t current_byte = 0;
153 for (size_t i = 0; i < n; ++i) {
154 output[i] = bytes[current_byte++];
155 current_byte %= arraysize(bytes);
156 }
157}
158
[email protected]fe2bc6a2009-03-23 16:52:20159void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29160 static const uint8 bytes[] = {
161 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
162 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
163 };
164 static size_t current_byte = 0;
165 for (size_t i = 0; i < n; ++i) {
166 output[i] = bytes[current_byte++];
167 current_byte %= arraysize(bytes);
168 }
169}
170
[email protected]fe2bc6a2009-03-23 16:52:20171std::string MockGetHostName() {
172 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29173}
174
[email protected]a937a06d2009-08-19 21:19:24175class CaptureGroupNameSocketPool : public TCPClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31176 public:
[email protected]a937a06d2009-08-19 21:19:24177 CaptureGroupNameSocketPool() : TCPClientSocketPool(0, 0, NULL, NULL) {}
[email protected]d80a4322009-08-14 07:07:49178 const std::string last_group_name_received() const {
179 return last_group_name_;
180 }
181
[email protected]684970b2009-08-14 04:54:46182 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49183 const void* socket_params,
[email protected]04e5be32009-06-26 20:00:31184 int priority,
185 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46186 CompletionCallback* callback,
187 LoadLog* load_log) {
[email protected]04e5be32009-06-26 20:00:31188 last_group_name_ = group_name;
189 return ERR_IO_PENDING;
190 }
[email protected]04e5be32009-06-26 20:00:31191 virtual void CancelRequest(const std::string& group_name,
192 const ClientSocketHandle* handle) { }
193 virtual void ReleaseSocket(const std::string& group_name,
194 ClientSocket* socket) {}
195 virtual void CloseIdleSockets() {}
196 virtual HostResolver* GetHostResolver() const {
197 return NULL;
198 }
199 virtual int IdleSocketCount() const {
200 return 0;
201 }
202 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
203 return 0;
204 }
205 virtual LoadState GetLoadState(const std::string& group_name,
206 const ClientSocketHandle* handle) const {
207 return LOAD_STATE_IDLE;
208 }
[email protected]d80a4322009-08-14 07:07:49209
210 private:
[email protected]04e5be32009-06-26 20:00:31211 std::string last_group_name_;
212};
213
[email protected]231d5a32008-09-13 00:45:27214//-----------------------------------------------------------------------------
215
216TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59217 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40218 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43219 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27220}
221
222TEST_F(HttpNetworkTransactionTest, SimpleGET) {
223 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35224 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
225 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42226 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27227 };
[email protected]231d5a32008-09-13 00:45:27228 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42229 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27230 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
231 EXPECT_EQ("hello world", out.response_data);
232}
233
234// Response with no status line.
235TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
236 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35237 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42238 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27239 };
[email protected]231d5a32008-09-13 00:45:27240 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42241 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27242 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
243 EXPECT_EQ("hello world", out.response_data);
244}
245
246// Allow up to 4 bytes of junk to precede status line.
247TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
248 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35249 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42250 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27251 };
252 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42253 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27254 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
255 EXPECT_EQ("DATA", out.response_data);
256}
257
258// Allow up to 4 bytes of junk to precede status line.
259TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
260 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35261 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42262 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27263 };
264 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42265 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27266 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
267 EXPECT_EQ("DATA", out.response_data);
268}
269
270// Beyond 4 bytes of slop and it should fail to find a status line.
271TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
272 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35273 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42274 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27275 };
276 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42277 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25278 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
279 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27280}
281
282// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
283TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
284 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35285 MockRead("\n"),
286 MockRead("\n"),
287 MockRead("Q"),
288 MockRead("J"),
289 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42290 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27291 };
292 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42293 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27294 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
295 EXPECT_EQ("DATA", out.response_data);
296}
297
298// Close the connection before enough bytes to have a status line.
299TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
300 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35301 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42302 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27303 };
304 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42305 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27306 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
307 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52308}
309
[email protected]f9d44aa2008-09-23 23:57:17310// Simulate a 204 response, lacking a Content-Length header, sent over a
311// persistent connection. The response should still terminate since a 204
312// cannot have a response body.
313TEST_F(HttpNetworkTransactionTest, StopsReading204) {
314 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35315 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
316 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42317 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17318 };
319 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42320 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17321 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
322 EXPECT_EQ("", out.response_data);
323}
324
[email protected]0877e3d2009-10-17 22:29:57325// A simple request using chunked encoding with some extra data after.
326// (Like might be seen in a pipelined response.)
327TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
328 MockRead data_reads[] = {
329 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
330 MockRead("5\r\nHello\r\n"),
331 MockRead("1\r\n"),
332 MockRead(" \r\n"),
333 MockRead("5\r\nworld\r\n"),
334 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
335 MockRead(false, OK),
336 };
337 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
338 EXPECT_EQ(OK, out.rv);
339 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
340 EXPECT_EQ("Hello world", out.response_data);
341}
342
[email protected]ef0faf2e72009-03-05 23:27:23343// Do a request using the HEAD method. Verify that we don't try to read the
344// message body (since HEAD has none).
345TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59346 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40347 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43348 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23349
[email protected]1c773ea12009-04-28 19:58:42350 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23351 request.method = "HEAD";
352 request.url = GURL("http://www.google.com/");
353 request.load_flags = 0;
354
355 MockWrite data_writes1[] = {
356 MockWrite("HEAD / HTTP/1.1\r\n"
357 "Host: www.google.com\r\n"
358 "Connection: keep-alive\r\n"
359 "Content-Length: 0\r\n\r\n"),
360 };
361 MockRead data_reads1[] = {
362 MockRead("HTTP/1.1 404 Not Found\r\n"),
363 MockRead("Server: Blah\r\n"),
364 MockRead("Content-Length: 1234\r\n\r\n"),
365
366 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42367 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23368 };
369
[email protected]69b43fe2009-06-15 09:47:37370 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59371 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23372
373 TestCompletionCallback callback1;
374
[email protected]684970b2009-08-14 04:54:46375 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42376 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23377
378 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42379 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23380
[email protected]1c773ea12009-04-28 19:58:42381 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23382 EXPECT_FALSE(response == NULL);
383
384 // Check that the headers got parsed.
385 EXPECT_TRUE(response->headers != NULL);
386 EXPECT_EQ(1234, response->headers->GetContentLength());
387 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
388
389 std::string server_header;
390 void* iter = NULL;
391 bool has_server_header = response->headers->EnumerateHeader(
392 &iter, "Server", &server_header);
393 EXPECT_TRUE(has_server_header);
394 EXPECT_EQ("Blah", server_header);
395
396 // Reading should give EOF right away, since there is no message body
397 // (despite non-zero content-length).
398 std::string response_data;
399 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42400 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23401 EXPECT_EQ("", response_data);
402}
403
initial.commit586acc5fe2008-07-26 22:42:52404TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59405 SessionDependencies session_deps;
406 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52407
408 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35409 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
410 MockRead("hello"),
411 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
412 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42413 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52414 };
[email protected]69b43fe2009-06-15 09:47:37415 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59416 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52417
418 const char* kExpectedResponseData[] = {
419 "hello", "world"
420 };
421
422 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43423 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52424
[email protected]1c773ea12009-04-28 19:58:42425 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52426 request.method = "GET";
427 request.url = GURL("http://www.google.com/");
428 request.load_flags = 0;
429
430 TestCompletionCallback callback;
431
[email protected]684970b2009-08-14 04:54:46432 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42433 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52434
435 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42436 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52437
[email protected]1c773ea12009-04-28 19:58:42438 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52439 EXPECT_TRUE(response != NULL);
440
441 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25442 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52443
444 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57445 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42446 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25447 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52448 }
449}
450
451TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59452 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40453 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43454 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52455
[email protected]1c773ea12009-04-28 19:58:42456 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52457 request.method = "POST";
458 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42459 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52460 request.upload_data->AppendBytes("foo", 3);
461 request.load_flags = 0;
462
463 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35464 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
465 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
466 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42467 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52468 };
[email protected]69b43fe2009-06-15 09:47:37469 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59470 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52471
472 TestCompletionCallback callback;
473
[email protected]684970b2009-08-14 04:54:46474 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42475 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52476
477 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42478 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52479
[email protected]1c773ea12009-04-28 19:58:42480 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52481 EXPECT_TRUE(response != NULL);
482
483 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25484 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52485
486 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57487 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42488 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25489 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52490}
491
[email protected]3a2d3662009-03-27 03:49:14492// This test is almost the same as Ignores100 above, but the response contains
493// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57494// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14495TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59496 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40497 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43498 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14499
[email protected]1c773ea12009-04-28 19:58:42500 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14501 request.method = "GET";
502 request.url = GURL("http://www.foo.com/");
503 request.load_flags = 0;
504
505 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57506 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
507 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14508 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42509 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14510 };
[email protected]69b43fe2009-06-15 09:47:37511 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59512 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3a2d3662009-03-27 03:49:14513
514 TestCompletionCallback callback;
515
[email protected]684970b2009-08-14 04:54:46516 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42517 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14518
519 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42520 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14521
[email protected]1c773ea12009-04-28 19:58:42522 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14523 EXPECT_TRUE(response != NULL);
524
525 EXPECT_TRUE(response->headers != NULL);
526 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
527
528 std::string response_data;
529 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42530 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14531 EXPECT_EQ("hello world", response_data);
532}
533
[email protected]3d2a59b2008-09-26 19:44:25534// read_failure specifies a read failure that should cause the network
535// transaction to resend the request.
536void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
537 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59538 SessionDependencies session_deps;
539 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52540
[email protected]1c773ea12009-04-28 19:58:42541 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52542 request.method = "GET";
543 request.url = GURL("http://www.foo.com/");
544 request.load_flags = 0;
545
546 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35547 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
548 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25549 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52550 };
[email protected]69b43fe2009-06-15 09:47:37551 StaticMockSocket data1(data1_reads, NULL);
[email protected]228ff742009-06-05 01:19:59552 session_deps.socket_factory.AddMockSocket(&data1);
initial.commit586acc5fe2008-07-26 22:42:52553
554 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35555 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
556 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42557 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52558 };
[email protected]69b43fe2009-06-15 09:47:37559 StaticMockSocket data2(data2_reads, NULL);
[email protected]228ff742009-06-05 01:19:59560 session_deps.socket_factory.AddMockSocket(&data2);
initial.commit586acc5fe2008-07-26 22:42:52561
562 const char* kExpectedResponseData[] = {
563 "hello", "world"
564 };
565
566 for (int i = 0; i < 2; ++i) {
567 TestCompletionCallback callback;
568
[email protected]5695b8c2009-09-30 21:36:43569 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52570
[email protected]684970b2009-08-14 04:54:46571 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42572 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52573
574 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42575 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52576
[email protected]1c773ea12009-04-28 19:58:42577 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52578 EXPECT_TRUE(response != NULL);
579
580 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25581 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52582
583 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57584 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42585 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25586 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52587 }
588}
[email protected]3d2a59b2008-09-26 19:44:25589
590TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42591 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25592 KeepAliveConnectionResendRequestTest(read_failure);
593}
594
595TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42596 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25597 KeepAliveConnectionResendRequestTest(read_failure);
598}
599
600TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59601 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40602 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43603 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25604
[email protected]1c773ea12009-04-28 19:58:42605 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25606 request.method = "GET";
607 request.url = GURL("http://www.google.com/");
608 request.load_flags = 0;
609
610 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42611 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35612 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
613 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42614 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25615 };
[email protected]69b43fe2009-06-15 09:47:37616 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59617 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3d2a59b2008-09-26 19:44:25618
619 TestCompletionCallback callback;
620
[email protected]684970b2009-08-14 04:54:46621 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42622 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25623
624 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42625 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25626
[email protected]1c773ea12009-04-28 19:58:42627 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25628 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25629}
630
631// What do various browsers do when the server closes a non-keepalive
632// connection without sending any response header or body?
633//
634// IE7: error page
635// Safari 3.1.2 (Windows): error page
636// Firefox 3.0.1: blank page
637// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42638// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
639// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25640TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
641 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42642 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35643 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
644 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42645 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25646 };
647 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42648 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25649}
[email protected]038e9a32008-10-08 22:40:16650
651// Test the request-challenge-retry sequence for basic auth.
652// (basic auth is the easiest to mock, because it has no randomness).
653TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59654 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40655 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43656 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16657
[email protected]1c773ea12009-04-28 19:58:42658 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16659 request.method = "GET";
660 request.url = GURL("http://www.google.com/");
661 request.load_flags = 0;
662
[email protected]f9ee6b52008-11-08 06:46:23663 MockWrite data_writes1[] = {
664 MockWrite("GET / HTTP/1.1\r\n"
665 "Host: www.google.com\r\n"
666 "Connection: keep-alive\r\n\r\n"),
667 };
668
[email protected]038e9a32008-10-08 22:40:16669 MockRead data_reads1[] = {
670 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
671 // Give a couple authenticate options (only the middle one is actually
672 // supported).
[email protected]22927ad2009-09-21 19:56:19673 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16674 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
675 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
676 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
677 // Large content-length -- won't matter, as connection will be reset.
678 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42679 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16680 };
681
682 // After calling trans->RestartWithAuth(), this is the request we should
683 // be issuing -- the final header line contains the credentials.
684 MockWrite data_writes2[] = {
685 MockWrite("GET / HTTP/1.1\r\n"
686 "Host: www.google.com\r\n"
687 "Connection: keep-alive\r\n"
688 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
689 };
690
691 // Lastly, the server responds with the actual content.
692 MockRead data_reads2[] = {
693 MockRead("HTTP/1.0 200 OK\r\n"),
694 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
695 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42696 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16697 };
698
[email protected]69b43fe2009-06-15 09:47:37699 StaticMockSocket data1(data_reads1, data_writes1);
700 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:59701 session_deps.socket_factory.AddMockSocket(&data1);
702 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]038e9a32008-10-08 22:40:16703
704 TestCompletionCallback callback1;
705
[email protected]684970b2009-08-14 04:54:46706 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42707 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16708
709 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42710 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16711
[email protected]1c773ea12009-04-28 19:58:42712 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16713 EXPECT_FALSE(response == NULL);
714
715 // The password prompt info should have been set in response->auth_challenge.
716 EXPECT_FALSE(response->auth_challenge.get() == NULL);
717
[email protected]71e4573a2009-05-21 22:03:00718 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16719 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
720 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
721
722 TestCompletionCallback callback2;
723
724 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42725 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16726
727 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42728 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16729
730 response = trans->GetResponseInfo();
731 EXPECT_FALSE(response == NULL);
732 EXPECT_TRUE(response->auth_challenge.get() == NULL);
733 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16734}
735
[email protected]861fcd52009-08-26 02:33:46736TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
737 SessionDependencies session_deps;
738 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43739 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46740
741 HttpRequestInfo request;
742 request.method = "GET";
743 request.url = GURL("http://www.google.com/");
744 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
745
746 MockWrite data_writes[] = {
747 MockWrite("GET / HTTP/1.1\r\n"
748 "Host: www.google.com\r\n"
749 "Connection: keep-alive\r\n\r\n"),
750 };
751
752 MockRead data_reads[] = {
753 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
754 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
755 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
756 // Large content-length -- won't matter, as connection will be reset.
757 MockRead("Content-Length: 10000\r\n\r\n"),
758 MockRead(false, ERR_FAILED),
759 };
760
761 StaticMockSocket data(data_reads, data_writes);
762 session_deps.socket_factory.AddMockSocket(&data);
763 TestCompletionCallback callback;
764
765 int rv = trans->Start(&request, &callback, NULL);
766 EXPECT_EQ(ERR_IO_PENDING, rv);
767
768 rv = callback.WaitForResult();
769 EXPECT_EQ(0, rv);
770
771 const HttpResponseInfo* response = trans->GetResponseInfo();
772 ASSERT_FALSE(response == NULL);
773 EXPECT_TRUE(response->auth_challenge.get() == NULL);
774}
775
[email protected]2d2697f92009-02-18 21:00:32776// Test the request-challenge-retry sequence for basic auth, over a keep-alive
777// connection.
778TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59779 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40780 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43781 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32782
[email protected]1c773ea12009-04-28 19:58:42783 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32784 request.method = "GET";
785 request.url = GURL("http://www.google.com/");
786 request.load_flags = 0;
787
788 MockWrite data_writes1[] = {
789 MockWrite("GET / HTTP/1.1\r\n"
790 "Host: www.google.com\r\n"
791 "Connection: keep-alive\r\n\r\n"),
792
793 // After calling trans->RestartWithAuth(), this is the request we should
794 // be issuing -- the final header line contains the credentials.
795 MockWrite("GET / HTTP/1.1\r\n"
796 "Host: www.google.com\r\n"
797 "Connection: keep-alive\r\n"
798 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
799 };
800
801 MockRead data_reads1[] = {
802 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
803 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
804 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
805 MockRead("Content-Length: 14\r\n\r\n"),
806 MockRead("Unauthorized\r\n"),
807
808 // Lastly, the server responds with the actual content.
809 MockRead("HTTP/1.1 200 OK\r\n"),
810 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
811 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42812 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32813 };
814
[email protected]69b43fe2009-06-15 09:47:37815 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59816 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32817
818 TestCompletionCallback callback1;
819
[email protected]684970b2009-08-14 04:54:46820 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42821 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32822
823 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42824 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32825
[email protected]1c773ea12009-04-28 19:58:42826 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32827 EXPECT_FALSE(response == NULL);
828
829 // The password prompt info should have been set in response->auth_challenge.
830 EXPECT_FALSE(response->auth_challenge.get() == NULL);
831
[email protected]71e4573a2009-05-21 22:03:00832 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32833 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
834 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
835
836 TestCompletionCallback callback2;
837
838 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42839 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32840
841 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42842 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32843
844 response = trans->GetResponseInfo();
845 EXPECT_FALSE(response == NULL);
846 EXPECT_TRUE(response->auth_challenge.get() == NULL);
847 EXPECT_EQ(100, response->headers->GetContentLength());
848}
849
850// Test the request-challenge-retry sequence for basic auth, over a keep-alive
851// connection and with no response body to drain.
852TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59853 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40854 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43855 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32856
[email protected]1c773ea12009-04-28 19:58:42857 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32858 request.method = "GET";
859 request.url = GURL("http://www.google.com/");
860 request.load_flags = 0;
861
862 MockWrite data_writes1[] = {
863 MockWrite("GET / HTTP/1.1\r\n"
864 "Host: www.google.com\r\n"
865 "Connection: keep-alive\r\n\r\n"),
866
867 // After calling trans->RestartWithAuth(), this is the request we should
868 // be issuing -- the final header line contains the credentials.
869 MockWrite("GET / HTTP/1.1\r\n"
870 "Host: www.google.com\r\n"
871 "Connection: keep-alive\r\n"
872 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
873 };
874
875 // Respond with 5 kb of response body.
876 std::string large_body_string("Unauthorized");
877 large_body_string.append(5 * 1024, ' ');
878 large_body_string.append("\r\n");
879
880 MockRead data_reads1[] = {
881 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
882 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
883 MockRead("Content-Length: 0\r\n\r\n"),
884
885 // Lastly, the server responds with the actual content.
886 MockRead("HTTP/1.1 200 OK\r\n"),
887 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
888 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42889 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32890 };
891
[email protected]69b43fe2009-06-15 09:47:37892 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59893 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32894
895 TestCompletionCallback callback1;
896
[email protected]684970b2009-08-14 04:54:46897 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42898 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32899
900 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42901 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32902
[email protected]1c773ea12009-04-28 19:58:42903 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32904 EXPECT_FALSE(response == NULL);
905
906 // The password prompt info should have been set in response->auth_challenge.
907 EXPECT_FALSE(response->auth_challenge.get() == NULL);
908
[email protected]71e4573a2009-05-21 22:03:00909 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32910 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
911 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
912
913 TestCompletionCallback callback2;
914
915 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42916 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32917
918 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42919 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32920
921 response = trans->GetResponseInfo();
922 EXPECT_FALSE(response == NULL);
923 EXPECT_TRUE(response->auth_challenge.get() == NULL);
924 EXPECT_EQ(100, response->headers->GetContentLength());
925}
926
927// Test the request-challenge-retry sequence for basic auth, over a keep-alive
928// connection and with a large response body to drain.
929TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:59930 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40931 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43932 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32933
[email protected]1c773ea12009-04-28 19:58:42934 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32935 request.method = "GET";
936 request.url = GURL("http://www.google.com/");
937 request.load_flags = 0;
938
939 MockWrite data_writes1[] = {
940 MockWrite("GET / HTTP/1.1\r\n"
941 "Host: www.google.com\r\n"
942 "Connection: keep-alive\r\n\r\n"),
943
944 // After calling trans->RestartWithAuth(), this is the request we should
945 // be issuing -- the final header line contains the credentials.
946 MockWrite("GET / HTTP/1.1\r\n"
947 "Host: www.google.com\r\n"
948 "Connection: keep-alive\r\n"
949 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
950 };
951
952 // Respond with 5 kb of response body.
953 std::string large_body_string("Unauthorized");
954 large_body_string.append(5 * 1024, ' ');
955 large_body_string.append("\r\n");
956
957 MockRead data_reads1[] = {
958 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
959 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
960 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
961 // 5134 = 12 + 5 * 1024 + 2
962 MockRead("Content-Length: 5134\r\n\r\n"),
963 MockRead(true, large_body_string.data(), large_body_string.size()),
964
965 // Lastly, the server responds with the actual content.
966 MockRead("HTTP/1.1 200 OK\r\n"),
967 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
968 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42969 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32970 };
971
[email protected]69b43fe2009-06-15 09:47:37972 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59973 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32974
975 TestCompletionCallback callback1;
976
[email protected]684970b2009-08-14 04:54:46977 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42978 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32979
980 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42981 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32982
[email protected]1c773ea12009-04-28 19:58:42983 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32984 EXPECT_FALSE(response == NULL);
985
986 // The password prompt info should have been set in response->auth_challenge.
987 EXPECT_FALSE(response->auth_challenge.get() == NULL);
988
[email protected]71e4573a2009-05-21 22:03:00989 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32990 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
991 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
992
993 TestCompletionCallback callback2;
994
995 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42996 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32997
998 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42999 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321000
1001 response = trans->GetResponseInfo();
1002 EXPECT_FALSE(response == NULL);
1003 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1004 EXPECT_EQ(100, response->headers->GetContentLength());
1005}
1006
1007// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1008// proxy connection, when setting up an SSL tunnel.
1009TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1010 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591011 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1012 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321013
[email protected]5695b8c2009-09-30 21:36:431014 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321015
[email protected]1c773ea12009-04-28 19:58:421016 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321017 request.method = "GET";
1018 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461019 // Ensure that proxy authentication is attempted even
1020 // when the no authentication data flag is set.
1021 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321022
1023 // Since we have proxy, should try to establish tunnel.
1024 MockWrite data_writes1[] = {
1025 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451026 "Host: www.google.com\r\n"
1027 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321028
1029 // After calling trans->RestartWithAuth(), this is the request we should
1030 // be issuing -- the final header line contains the credentials.
1031 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1032 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451033 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321034 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1035 };
1036
1037 // The proxy responds to the connect with a 407, using a persistent
1038 // connection.
1039 MockRead data_reads1[] = {
1040 // No credentials.
1041 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1042 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1043 MockRead("Content-Length: 10\r\n\r\n"),
1044 MockRead("0123456789"),
1045
1046 // Wrong credentials (wrong password).
1047 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1048 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1049 MockRead("Content-Length: 10\r\n\r\n"),
1050 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421051 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321052 };
1053
[email protected]69b43fe2009-06-15 09:47:371054 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:591055 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:321056
1057 TestCompletionCallback callback1;
1058
[email protected]684970b2009-08-14 04:54:461059 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421060 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321061
1062 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421063 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321064
[email protected]1c773ea12009-04-28 19:58:421065 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321066 EXPECT_FALSE(response == NULL);
1067
1068 EXPECT_TRUE(response->headers->IsKeepAlive());
1069 EXPECT_EQ(407, response->headers->response_code());
1070 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421071 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321072
1073 // The password prompt info should have been set in response->auth_challenge.
1074 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1075
[email protected]71e4573a2009-05-21 22:03:001076 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321077 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1078 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1079
1080 TestCompletionCallback callback2;
1081
1082 // Wrong password (should be "bar").
1083 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421084 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321085
1086 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421087 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321088
1089 response = trans->GetResponseInfo();
1090 EXPECT_FALSE(response == NULL);
1091
1092 EXPECT_TRUE(response->headers->IsKeepAlive());
1093 EXPECT_EQ(407, response->headers->response_code());
1094 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421095 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321096
1097 // The password prompt info should have been set in response->auth_challenge.
1098 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1099
[email protected]71e4573a2009-05-21 22:03:001100 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321101 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1102 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1103}
1104
[email protected]a8e9b162009-03-12 00:06:441105// Test that we don't read the response body when we fail to establish a tunnel,
1106// even if the user cancels the proxy's auth attempt.
1107TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1108 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591109 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441110
[email protected]e44de5d2009-06-05 20:12:451111 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441112
[email protected]5695b8c2009-09-30 21:36:431113 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441114
[email protected]1c773ea12009-04-28 19:58:421115 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441116 request.method = "GET";
1117 request.url = GURL("https://www.google.com/");
1118 request.load_flags = 0;
1119
1120 // Since we have proxy, should try to establish tunnel.
1121 MockWrite data_writes[] = {
1122 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451123 "Host: www.google.com\r\n"
1124 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441125 };
1126
1127 // The proxy responds to the connect with a 407.
1128 MockRead data_reads[] = {
1129 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1130 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1131 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421132 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441133 };
1134
[email protected]69b43fe2009-06-15 09:47:371135 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:591136 session_deps.socket_factory.AddMockSocket(&data);
[email protected]a8e9b162009-03-12 00:06:441137
1138 TestCompletionCallback callback;
1139
[email protected]684970b2009-08-14 04:54:461140 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421141 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441142
1143 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421144 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441145
[email protected]1c773ea12009-04-28 19:58:421146 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441147 EXPECT_FALSE(response == NULL);
1148
1149 EXPECT_TRUE(response->headers->IsKeepAlive());
1150 EXPECT_EQ(407, response->headers->response_code());
1151 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421152 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441153
1154 std::string response_data;
1155 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421156 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441157}
1158
[email protected]ff007e162009-05-23 09:13:151159void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081160 const MockRead& status, int expected_status) {
1161 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591162 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081163
[email protected]228ff742009-06-05 01:19:591164 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081165
[email protected]5695b8c2009-09-30 21:36:431166 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081167
[email protected]1c773ea12009-04-28 19:58:421168 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081169 request.method = "GET";
1170 request.url = GURL("https://www.google.com/");
1171 request.load_flags = 0;
1172
1173 // Since we have proxy, should try to establish tunnel.
1174 MockWrite data_writes[] = {
1175 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451176 "Host: www.google.com\r\n"
1177 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081178 };
1179
1180 MockRead data_reads[] = {
1181 status,
1182 MockRead("Content-Length: 10\r\n\r\n"),
1183 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421184 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081185 };
1186
[email protected]69b43fe2009-06-15 09:47:371187 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:591188 session_deps.socket_factory.AddMockSocket(&data);
[email protected]c744cf22009-02-27 07:28:081189
1190 TestCompletionCallback callback;
1191
[email protected]684970b2009-08-14 04:54:461192 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421193 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081194
1195 rv = callback.WaitForResult();
1196 EXPECT_EQ(expected_status, rv);
1197}
1198
[email protected]ff007e162009-05-23 09:13:151199void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081200 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421201 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081202}
1203
1204TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1205 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1206}
1207
1208TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1209 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1210}
1211
1212TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1213 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1214}
1215
1216TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1217 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1218}
1219
1220TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1221 ConnectStatusHelper(
1222 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1223}
1224
1225TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1226 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1227}
1228
1229TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1230 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1231}
1232
1233TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1234 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1235}
1236
1237TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1238 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1239}
1240
1241TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1242 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1243}
1244
1245TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1246 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1247}
1248
1249TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1250 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1251}
1252
1253TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1254 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1255}
1256
1257TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1258 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1259}
1260
1261TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1262 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1263}
1264
1265TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1266 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1267}
1268
1269TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1270 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1271}
1272
1273TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1274 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1275}
1276
1277TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1278 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1279}
1280
1281TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1282 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1283}
1284
1285TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1286 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1287}
1288
1289TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1290 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1291}
1292
1293TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1294 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1295}
1296
1297TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1298 ConnectStatusHelperWithExpectedStatus(
1299 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421300 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081301}
1302
1303TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1304 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1305}
1306
1307TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1308 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1309}
1310
1311TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1312 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1313}
1314
1315TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1316 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1317}
1318
1319TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1320 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1321}
1322
1323TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1324 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1325}
1326
1327TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1328 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1329}
1330
1331TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1332 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1333}
1334
1335TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1336 ConnectStatusHelper(
1337 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1338}
1339
1340TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1341 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1342}
1343
1344TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1345 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1346}
1347
1348TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1349 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1350}
1351
1352TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1353 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1354}
1355
1356TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1357 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1358}
1359
1360TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1361 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1362}
1363
1364TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1365 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1366}
1367
[email protected]038e9a32008-10-08 22:40:161368// Test the flow when both the proxy server AND origin server require
1369// authentication. Again, this uses basic auth for both since that is
1370// the simplest to mock.
1371TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591372 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011373
[email protected]038e9a32008-10-08 22:40:161374 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421375 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431376 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161377
[email protected]1c773ea12009-04-28 19:58:421378 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161379 request.method = "GET";
1380 request.url = GURL("http://www.google.com/");
1381 request.load_flags = 0;
1382
[email protected]f9ee6b52008-11-08 06:46:231383 MockWrite data_writes1[] = {
1384 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1385 "Host: www.google.com\r\n"
1386 "Proxy-Connection: keep-alive\r\n\r\n"),
1387 };
1388
[email protected]038e9a32008-10-08 22:40:161389 MockRead data_reads1[] = {
1390 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1391 // Give a couple authenticate options (only the middle one is actually
1392 // supported).
[email protected]22927ad2009-09-21 19:56:191393 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161394 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1395 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1396 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1397 // Large content-length -- won't matter, as connection will be reset.
1398 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421399 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161400 };
1401
1402 // After calling trans->RestartWithAuth() the first time, this is the
1403 // request we should be issuing -- the final header line contains the
1404 // proxy's credentials.
1405 MockWrite data_writes2[] = {
1406 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1407 "Host: www.google.com\r\n"
1408 "Proxy-Connection: keep-alive\r\n"
1409 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1410 };
1411
1412 // Now the proxy server lets the request pass through to origin server.
1413 // The origin server responds with a 401.
1414 MockRead data_reads2[] = {
1415 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1416 // Note: We are using the same realm-name as the proxy server. This is
1417 // completely valid, as realms are unique across hosts.
1418 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1419 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1420 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421421 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161422 };
1423
1424 // After calling trans->RestartWithAuth() the second time, we should send
1425 // the credentials for both the proxy and origin server.
1426 MockWrite data_writes3[] = {
1427 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1428 "Host: www.google.com\r\n"
1429 "Proxy-Connection: keep-alive\r\n"
1430 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1431 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1432 };
1433
1434 // Lastly we get the desired content.
1435 MockRead data_reads3[] = {
1436 MockRead("HTTP/1.0 200 OK\r\n"),
1437 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1438 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421439 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161440 };
1441
[email protected]69b43fe2009-06-15 09:47:371442 StaticMockSocket data1(data_reads1, data_writes1);
1443 StaticMockSocket data2(data_reads2, data_writes2);
1444 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:591445 session_deps.socket_factory.AddMockSocket(&data1);
1446 session_deps.socket_factory.AddMockSocket(&data2);
1447 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]038e9a32008-10-08 22:40:161448
1449 TestCompletionCallback callback1;
1450
[email protected]684970b2009-08-14 04:54:461451 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421452 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161453
1454 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421455 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161456
[email protected]1c773ea12009-04-28 19:58:421457 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161458 EXPECT_FALSE(response == NULL);
1459
1460 // The password prompt info should have been set in response->auth_challenge.
1461 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1462
[email protected]71e4573a2009-05-21 22:03:001463 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161464 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1465 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1466
1467 TestCompletionCallback callback2;
1468
1469 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421470 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161471
1472 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421473 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161474
1475 response = trans->GetResponseInfo();
1476 EXPECT_FALSE(response == NULL);
1477 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1478
[email protected]71e4573a2009-05-21 22:03:001479 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161480 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1481 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1482
1483 TestCompletionCallback callback3;
1484
1485 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421486 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161487
1488 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421489 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161490
1491 response = trans->GetResponseInfo();
1492 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1493 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161494}
[email protected]4ddaf2502008-10-23 18:26:191495
[email protected]ea9dc9a2009-09-05 00:43:321496// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1497// can't hook into its internals to cause it to generate predictable NTLM
1498// authorization headers.
1499#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291500// The NTLM authentication unit tests were generated by capturing the HTTP
1501// requests and responses using Fiddler 2 and inspecting the generated random
1502// bytes in the debugger.
1503
1504// Enter the correct password and authenticate successfully.
1505TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421506 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201507 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591508 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401509 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431510 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241511
[email protected]1c773ea12009-04-28 19:58:421512 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241513 request.method = "GET";
1514 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1515 request.load_flags = 0;
1516
1517 MockWrite data_writes1[] = {
1518 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1519 "Host: 172.22.68.17\r\n"
1520 "Connection: keep-alive\r\n\r\n"),
1521 };
1522
1523 MockRead data_reads1[] = {
1524 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1525 // Negotiate and NTLM are often requested together. We only support NTLM.
1526 MockRead("WWW-Authenticate: Negotiate\r\n"),
1527 MockRead("WWW-Authenticate: NTLM\r\n"),
1528 MockRead("Connection: close\r\n"),
1529 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361530 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241531 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421532 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241533 };
1534
1535 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221536 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241537 // request we should be issuing -- the final header line contains a Type
1538 // 1 message.
1539 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1540 "Host: 172.22.68.17\r\n"
1541 "Connection: keep-alive\r\n"
1542 "Authorization: NTLM "
1543 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1544
1545 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1546 // (the credentials for the origin server). The second request continues
1547 // on the same connection.
1548 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1549 "Host: 172.22.68.17\r\n"
1550 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291551 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1552 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1553 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1554 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1555 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241556 };
1557
1558 MockRead data_reads2[] = {
1559 // The origin server responds with a Type 2 message.
1560 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1561 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291562 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241563 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1564 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1565 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1566 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1567 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1568 "BtAAAAAAA=\r\n"),
1569 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361570 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241571 MockRead("You are not authorized to view this page\r\n"),
1572
1573 // Lastly we get the desired content.
1574 MockRead("HTTP/1.1 200 OK\r\n"),
1575 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1576 MockRead("Content-Length: 13\r\n\r\n"),
1577 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421578 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241579 };
1580
[email protected]69b43fe2009-06-15 09:47:371581 StaticMockSocket data1(data_reads1, data_writes1);
1582 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:591583 session_deps.socket_factory.AddMockSocket(&data1);
1584 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]3f918782009-02-28 01:29:241585
1586 TestCompletionCallback callback1;
1587
[email protected]684970b2009-08-14 04:54:461588 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421589 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241590
1591 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421592 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241593
[email protected]0757e7702009-03-27 04:00:221594 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1595 TestCompletionCallback callback2;
1596 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421597 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221598 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421599 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221600 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1601
[email protected]1c773ea12009-04-28 19:58:421602 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241603 EXPECT_FALSE(response == NULL);
1604
1605 // The password prompt info should have been set in response->auth_challenge.
1606 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1607
[email protected]71e4573a2009-05-21 22:03:001608 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241609 EXPECT_EQ(L"", response->auth_challenge->realm);
1610 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1611
[email protected]0757e7702009-03-27 04:00:221612 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241613
[email protected]0757e7702009-03-27 04:00:221614 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421615 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241616
[email protected]0757e7702009-03-27 04:00:221617 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421618 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241619
1620 response = trans->GetResponseInfo();
1621 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1622 EXPECT_EQ(13, response->headers->GetContentLength());
1623}
1624
[email protected]385a4672009-03-11 22:21:291625// Enter a wrong password, and then the correct one.
1626TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421627 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201628 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591629 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401630 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431631 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291632
[email protected]1c773ea12009-04-28 19:58:421633 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291634 request.method = "GET";
1635 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1636 request.load_flags = 0;
1637
1638 MockWrite data_writes1[] = {
1639 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1640 "Host: 172.22.68.17\r\n"
1641 "Connection: keep-alive\r\n\r\n"),
1642 };
1643
1644 MockRead data_reads1[] = {
1645 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1646 // Negotiate and NTLM are often requested together. We only support NTLM.
1647 MockRead("WWW-Authenticate: Negotiate\r\n"),
1648 MockRead("WWW-Authenticate: NTLM\r\n"),
1649 MockRead("Connection: close\r\n"),
1650 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361651 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291652 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421653 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291654 };
1655
1656 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221657 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291658 // request we should be issuing -- the final header line contains a Type
1659 // 1 message.
1660 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1661 "Host: 172.22.68.17\r\n"
1662 "Connection: keep-alive\r\n"
1663 "Authorization: NTLM "
1664 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1665
1666 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1667 // (the credentials for the origin server). The second request continues
1668 // on the same connection.
1669 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1670 "Host: 172.22.68.17\r\n"
1671 "Connection: keep-alive\r\n"
1672 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1673 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1674 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1675 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1676 "4Ww7b7E=\r\n\r\n"),
1677 };
1678
1679 MockRead data_reads2[] = {
1680 // The origin server responds with a Type 2 message.
1681 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1682 MockRead("WWW-Authenticate: NTLM "
1683 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1684 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1685 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1686 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1687 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1688 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1689 "BtAAAAAAA=\r\n"),
1690 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361691 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291692 MockRead("You are not authorized to view this page\r\n"),
1693
1694 // Wrong password.
1695 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1696 MockRead("WWW-Authenticate: Negotiate\r\n"),
1697 MockRead("WWW-Authenticate: NTLM\r\n"),
1698 MockRead("Connection: close\r\n"),
1699 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361700 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291701 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421702 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291703 };
1704
1705 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221706 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291707 // request we should be issuing -- the final header line contains a Type
1708 // 1 message.
1709 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1710 "Host: 172.22.68.17\r\n"
1711 "Connection: keep-alive\r\n"
1712 "Authorization: NTLM "
1713 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1714
1715 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1716 // (the credentials for the origin server). The second request continues
1717 // on the same connection.
1718 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1719 "Host: 172.22.68.17\r\n"
1720 "Connection: keep-alive\r\n"
1721 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1722 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1723 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1724 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1725 "+4MUm7c=\r\n\r\n"),
1726 };
1727
1728 MockRead data_reads3[] = {
1729 // The origin server responds with a Type 2 message.
1730 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1731 MockRead("WWW-Authenticate: NTLM "
1732 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1733 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1734 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1735 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1736 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1737 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1738 "BtAAAAAAA=\r\n"),
1739 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361740 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291741 MockRead("You are not authorized to view this page\r\n"),
1742
1743 // Lastly we get the desired content.
1744 MockRead("HTTP/1.1 200 OK\r\n"),
1745 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1746 MockRead("Content-Length: 13\r\n\r\n"),
1747 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421748 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291749 };
1750
[email protected]69b43fe2009-06-15 09:47:371751 StaticMockSocket data1(data_reads1, data_writes1);
1752 StaticMockSocket data2(data_reads2, data_writes2);
1753 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:591754 session_deps.socket_factory.AddMockSocket(&data1);
1755 session_deps.socket_factory.AddMockSocket(&data2);
1756 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]385a4672009-03-11 22:21:291757
1758 TestCompletionCallback callback1;
1759
[email protected]684970b2009-08-14 04:54:461760 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421761 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291762
1763 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421764 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291765
[email protected]0757e7702009-03-27 04:00:221766 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291767 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221768 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421769 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291770 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421771 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221772 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291773
[email protected]1c773ea12009-04-28 19:58:421774 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291775 EXPECT_FALSE(response == NULL);
1776
1777 // The password prompt info should have been set in response->auth_challenge.
1778 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1779
[email protected]71e4573a2009-05-21 22:03:001780 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291781 EXPECT_EQ(L"", response->auth_challenge->realm);
1782 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1783
1784 TestCompletionCallback callback3;
1785
[email protected]0757e7702009-03-27 04:00:221786 // Enter the wrong password.
1787 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421788 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291789
1790 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421791 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291792
[email protected]0757e7702009-03-27 04:00:221793 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1794 TestCompletionCallback callback4;
1795 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421796 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221797 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421798 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221799 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1800
1801 response = trans->GetResponseInfo();
1802 EXPECT_FALSE(response == NULL);
1803
1804 // The password prompt info should have been set in response->auth_challenge.
1805 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1806
[email protected]71e4573a2009-05-21 22:03:001807 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221808 EXPECT_EQ(L"", response->auth_challenge->realm);
1809 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1810
1811 TestCompletionCallback callback5;
1812
1813 // Now enter the right password.
1814 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:421815 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221816
1817 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421818 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221819
[email protected]385a4672009-03-11 22:21:291820 response = trans->GetResponseInfo();
1821 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1822 EXPECT_EQ(13, response->headers->GetContentLength());
1823}
[email protected]ea9dc9a2009-09-05 00:43:321824#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:291825
[email protected]4ddaf2502008-10-23 18:26:191826// Test reading a server response which has only headers, and no body.
1827// After some maximum number of bytes is consumed, the transaction should
1828// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
1829TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:591830 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401831 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431832 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:191833
[email protected]1c773ea12009-04-28 19:58:421834 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:191835 request.method = "GET";
1836 request.url = GURL("http://www.google.com/");
1837 request.load_flags = 0;
1838
[email protected]b75b7b2f2009-10-06 00:54:531839 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:431840 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:531841 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:191842
1843 MockRead data_reads[] = {
1844 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:431845 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:191846 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:421847 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:191848 };
[email protected]69b43fe2009-06-15 09:47:371849 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591850 session_deps.socket_factory.AddMockSocket(&data);
[email protected]4ddaf2502008-10-23 18:26:191851
1852 TestCompletionCallback callback;
1853
[email protected]684970b2009-08-14 04:54:461854 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421855 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:191856
1857 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421858 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:191859
[email protected]1c773ea12009-04-28 19:58:421860 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:191861 EXPECT_TRUE(response == NULL);
1862}
[email protected]f4e426b2008-11-05 00:24:491863
1864// Make sure that we don't try to reuse a TCPClientSocket when failing to
1865// establish tunnel.
1866// http://code.google.com/p/chromium/issues/detail?id=3772
1867TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
1868 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591869 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011870
[email protected]228ff742009-06-05 01:19:591871 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:491872
[email protected]5695b8c2009-09-30 21:36:431873 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:491874
[email protected]1c773ea12009-04-28 19:58:421875 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:491876 request.method = "GET";
1877 request.url = GURL("https://www.google.com/");
1878 request.load_flags = 0;
1879
1880 // Since we have proxy, should try to establish tunnel.
1881 MockWrite data_writes1[] = {
1882 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451883 "Host: www.google.com\r\n"
1884 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:491885 };
1886
[email protected]77848d12008-11-14 00:00:221887 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:491888 // connection. Usually a proxy would return 501 (not implemented),
1889 // or 200 (tunnel established).
1890 MockRead data_reads1[] = {
1891 MockRead("HTTP/1.1 404 Not Found\r\n"),
1892 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421893 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:491894 };
1895
[email protected]69b43fe2009-06-15 09:47:371896 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:591897 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f4e426b2008-11-05 00:24:491898
1899 TestCompletionCallback callback1;
1900
[email protected]684970b2009-08-14 04:54:461901 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421902 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:491903
1904 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421905 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:491906
[email protected]1c773ea12009-04-28 19:58:421907 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:081908 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:491909
[email protected]b4404c02009-04-10 16:38:521910 // Empty the current queue. This is necessary because idle sockets are
1911 // added to the connection pool asynchronously with a PostTask.
1912 MessageLoop::current()->RunAllPending();
1913
[email protected]f4e426b2008-11-05 00:24:491914 // We now check to make sure the TCPClientSocket was not added back to
1915 // the pool.
[email protected]a937a06d2009-08-19 21:19:241916 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:491917 trans.reset();
[email protected]b4404c02009-04-10 16:38:521918 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:491919 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:241920 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:491921}
[email protected]372d34a2008-11-05 21:30:511922
[email protected]1b157c02009-04-21 01:55:401923// Make sure that we recycle a socket after reading all of the response body.
1924TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:591925 SessionDependencies session_deps;
1926 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:401927
[email protected]5695b8c2009-09-30 21:36:431928 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:401929
[email protected]1c773ea12009-04-28 19:58:421930 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:401931 request.method = "GET";
1932 request.url = GURL("http://www.google.com/");
1933 request.load_flags = 0;
1934
1935 MockRead data_reads[] = {
1936 // A part of the response body is received with the response headers.
1937 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
1938 // The rest of the response body is received in two parts.
1939 MockRead("lo"),
1940 MockRead(" world"),
1941 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421942 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:401943 };
1944
[email protected]69b43fe2009-06-15 09:47:371945 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591946 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1b157c02009-04-21 01:55:401947
1948 TestCompletionCallback callback;
1949
[email protected]684970b2009-08-14 04:54:461950 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421951 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:401952
1953 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421954 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401955
[email protected]1c773ea12009-04-28 19:58:421956 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:401957 EXPECT_TRUE(response != NULL);
1958
1959 EXPECT_TRUE(response->headers != NULL);
1960 std::string status_line = response->headers->GetStatusLine();
1961 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
1962
[email protected]a937a06d2009-08-19 21:19:241963 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:401964
1965 std::string response_data;
1966 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421967 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401968 EXPECT_EQ("hello world", response_data);
1969
1970 // Empty the current queue. This is necessary because idle sockets are
1971 // added to the connection pool asynchronously with a PostTask.
1972 MessageLoop::current()->RunAllPending();
1973
1974 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:241975 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:401976}
1977
[email protected]b4404c02009-04-10 16:38:521978// Make sure that we recycle a socket after a zero-length response.
1979// http://crbug.com/9880
1980TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:591981 SessionDependencies session_deps;
1982 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:521983
[email protected]5695b8c2009-09-30 21:36:431984 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:521985
[email protected]1c773ea12009-04-28 19:58:421986 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:521987 request.method = "GET";
1988 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
1989 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
1990 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
1991 "rt=prt.2642,ol.2649,xjs.2951");
1992 request.load_flags = 0;
1993
1994 MockRead data_reads[] = {
1995 MockRead("HTTP/1.1 204 No Content\r\n"
1996 "Content-Length: 0\r\n"
1997 "Content-Type: text/html\r\n\r\n"),
1998 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421999 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522000 };
2001
[email protected]69b43fe2009-06-15 09:47:372002 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:592003 session_deps.socket_factory.AddMockSocket(&data);
[email protected]b4404c02009-04-10 16:38:522004
2005 TestCompletionCallback callback;
2006
[email protected]684970b2009-08-14 04:54:462007 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422008 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522009
2010 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422011 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522012
[email protected]1c773ea12009-04-28 19:58:422013 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522014 EXPECT_TRUE(response != NULL);
2015
2016 EXPECT_TRUE(response->headers != NULL);
2017 std::string status_line = response->headers->GetStatusLine();
2018 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2019
[email protected]a937a06d2009-08-19 21:19:242020 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522021
2022 std::string response_data;
2023 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422024 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522025 EXPECT_EQ("", response_data);
2026
2027 // Empty the current queue. This is necessary because idle sockets are
2028 // added to the connection pool asynchronously with a PostTask.
2029 MessageLoop::current()->RunAllPending();
2030
2031 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242032 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522033}
2034
[email protected]372d34a2008-11-05 21:30:512035TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422036 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512037 // Transaction 1: a GET request that succeeds. The socket is recycled
2038 // after use.
2039 request[0].method = "GET";
2040 request[0].url = GURL("http://www.google.com/");
2041 request[0].load_flags = 0;
2042 // Transaction 2: a POST request. Reuses the socket kept alive from
2043 // transaction 1. The first attempts fails when writing the POST data.
2044 // This causes the transaction to retry with a new socket. The second
2045 // attempt succeeds.
2046 request[1].method = "POST";
2047 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422048 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512049 request[1].upload_data->AppendBytes("foo", 3);
2050 request[1].load_flags = 0;
2051
[email protected]228ff742009-06-05 01:19:592052 SessionDependencies session_deps;
2053 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512054
2055 // The first socket is used for transaction 1 and the first attempt of
2056 // transaction 2.
2057
2058 // The response of transaction 1.
2059 MockRead data_reads1[] = {
2060 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2061 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422062 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512063 };
2064 // The mock write results of transaction 1 and the first attempt of
2065 // transaction 2.
2066 MockWrite data_writes1[] = {
2067 MockWrite(false, 64), // GET
2068 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422069 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512070 };
[email protected]69b43fe2009-06-15 09:47:372071 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:512072
2073 // The second socket is used for the second attempt of transaction 2.
2074
2075 // The response of transaction 2.
2076 MockRead data_reads2[] = {
2077 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2078 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422079 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512080 };
2081 // The mock write results of the second attempt of transaction 2.
2082 MockWrite data_writes2[] = {
2083 MockWrite(false, 93), // POST
2084 MockWrite(false, 3), // POST data
2085 };
[email protected]69b43fe2009-06-15 09:47:372086 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:512087
[email protected]228ff742009-06-05 01:19:592088 session_deps.socket_factory.AddMockSocket(&data1);
2089 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]372d34a2008-11-05 21:30:512090
2091 const char* kExpectedResponseData[] = {
2092 "hello world", "welcome"
2093 };
2094
2095 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422096 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432097 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512098
2099 TestCompletionCallback callback;
2100
[email protected]684970b2009-08-14 04:54:462101 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422102 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512103
2104 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422105 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512106
[email protected]1c773ea12009-04-28 19:58:422107 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512108 EXPECT_TRUE(response != NULL);
2109
2110 EXPECT_TRUE(response->headers != NULL);
2111 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2112
2113 std::string response_data;
2114 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422115 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512116 EXPECT_EQ(kExpectedResponseData[i], response_data);
2117 }
2118}
[email protected]f9ee6b52008-11-08 06:46:232119
2120// Test the request-challenge-retry sequence for basic auth when there is
2121// an identity in the URL. The request should be sent as normal, but when
2122// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322123TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592124 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402125 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432126 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232127
[email protected]1c773ea12009-04-28 19:58:422128 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232129 request.method = "GET";
2130 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292131 request.url = GURL("http://foo:b@[email protected]/");
2132
2133 // The password contains an escaped character -- for this test to pass it
2134 // will need to be unescaped by HttpNetworkTransaction.
2135 EXPECT_EQ("b%40r", request.url.password());
2136
[email protected]ea9dc9a2009-09-05 00:43:322137 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232138
2139 MockWrite data_writes1[] = {
2140 MockWrite("GET / HTTP/1.1\r\n"
2141 "Host: www.google.com\r\n"
2142 "Connection: keep-alive\r\n\r\n"),
2143 };
2144
2145 MockRead data_reads1[] = {
2146 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2147 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2148 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422149 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232150 };
2151
2152 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322153 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232154 MockWrite data_writes2[] = {
2155 MockWrite("GET / HTTP/1.1\r\n"
2156 "Host: www.google.com\r\n"
2157 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292158 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232159 };
2160
2161 MockRead data_reads2[] = {
2162 MockRead("HTTP/1.0 200 OK\r\n"),
2163 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422164 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232165 };
2166
[email protected]69b43fe2009-06-15 09:47:372167 StaticMockSocket data1(data_reads1, data_writes1);
2168 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592169 session_deps.socket_factory.AddMockSocket(&data1);
2170 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232171
2172 TestCompletionCallback callback1;
2173
[email protected]684970b2009-08-14 04:54:462174 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422175 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232176
2177 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422178 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232179
[email protected]0757e7702009-03-27 04:00:222180 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2181 TestCompletionCallback callback2;
2182 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422183 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222184 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422185 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222186 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2187
[email protected]1c773ea12009-04-28 19:58:422188 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232189 EXPECT_FALSE(response == NULL);
2190
2191 // There is no challenge info, since the identity in URL worked.
2192 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2193
2194 EXPECT_EQ(100, response->headers->GetContentLength());
2195
2196 // Empty the current queue.
2197 MessageLoop::current()->RunAllPending();
2198}
2199
[email protected]ea9dc9a2009-09-05 00:43:322200// Test the request-challenge-retry sequence for basic auth when there is
2201// an incorrect identity in the URL. The identity from the URL should be used
2202// only once.
2203TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2204 SessionDependencies session_deps;
2205 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432206 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322207
2208 HttpRequestInfo request;
2209 request.method = "GET";
2210 // Note: the URL has a username:password in it. The password "baz" is
2211 // wrong (should be "bar").
2212 request.url = GURL("http://foo:[email protected]/");
2213
2214 request.load_flags = LOAD_NORMAL;
2215
2216 MockWrite data_writes1[] = {
2217 MockWrite("GET / HTTP/1.1\r\n"
2218 "Host: www.google.com\r\n"
2219 "Connection: keep-alive\r\n\r\n"),
2220 };
2221
2222 MockRead data_reads1[] = {
2223 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2224 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2225 MockRead("Content-Length: 10\r\n\r\n"),
2226 MockRead(false, ERR_FAILED),
2227 };
2228
2229 // After the challenge above, the transaction will be restarted using the
2230 // identity from the url (foo, baz) to answer the challenge.
2231 MockWrite data_writes2[] = {
2232 MockWrite("GET / HTTP/1.1\r\n"
2233 "Host: www.google.com\r\n"
2234 "Connection: keep-alive\r\n"
2235 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2236 };
2237
2238 MockRead data_reads2[] = {
2239 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2240 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2241 MockRead("Content-Length: 10\r\n\r\n"),
2242 MockRead(false, ERR_FAILED),
2243 };
2244
2245 // After the challenge above, the transaction will be restarted using the
2246 // identity supplied by the user (foo, bar) to answer the challenge.
2247 MockWrite data_writes3[] = {
2248 MockWrite("GET / HTTP/1.1\r\n"
2249 "Host: www.google.com\r\n"
2250 "Connection: keep-alive\r\n"
2251 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2252 };
2253
2254 MockRead data_reads3[] = {
2255 MockRead("HTTP/1.0 200 OK\r\n"),
2256 MockRead("Content-Length: 100\r\n\r\n"),
2257 MockRead(false, OK),
2258 };
2259
2260 StaticMockSocket data1(data_reads1, data_writes1);
2261 StaticMockSocket data2(data_reads2, data_writes2);
2262 StaticMockSocket data3(data_reads3, data_writes3);
2263 session_deps.socket_factory.AddMockSocket(&data1);
2264 session_deps.socket_factory.AddMockSocket(&data2);
2265 session_deps.socket_factory.AddMockSocket(&data3);
2266
2267 TestCompletionCallback callback1;
2268
2269 int rv = trans->Start(&request, &callback1, NULL);
2270 EXPECT_EQ(ERR_IO_PENDING, rv);
2271
2272 rv = callback1.WaitForResult();
2273 EXPECT_EQ(OK, rv);
2274
2275 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2276 TestCompletionCallback callback2;
2277 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2278 EXPECT_EQ(ERR_IO_PENDING, rv);
2279 rv = callback2.WaitForResult();
2280 EXPECT_EQ(OK, rv);
2281 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2282
2283 const HttpResponseInfo* response = trans->GetResponseInfo();
2284 EXPECT_FALSE(response == NULL);
2285 // The password prompt info should have been set in response->auth_challenge.
2286 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2287
2288 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2289 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2290 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2291
2292 TestCompletionCallback callback3;
2293 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2294 EXPECT_EQ(ERR_IO_PENDING, rv);
2295 rv = callback3.WaitForResult();
2296 EXPECT_EQ(OK, rv);
2297 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2298
2299 response = trans->GetResponseInfo();
2300 EXPECT_FALSE(response == NULL);
2301
2302 // There is no challenge info, since the identity worked.
2303 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2304
2305 EXPECT_EQ(100, response->headers->GetContentLength());
2306
2307 // Empty the current queue.
2308 MessageLoop::current()->RunAllPending();
2309}
2310
[email protected]f9ee6b52008-11-08 06:46:232311// Test that previously tried username/passwords for a realm get re-used.
2312TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592313 SessionDependencies session_deps;
2314 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232315
2316 // Transaction 1: authenticate (foo, bar) on MyRealm1
2317 {
[email protected]5695b8c2009-09-30 21:36:432318 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232319
[email protected]1c773ea12009-04-28 19:58:422320 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232321 request.method = "GET";
2322 request.url = GURL("http://www.google.com/x/y/z");
2323 request.load_flags = 0;
2324
2325 MockWrite data_writes1[] = {
2326 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2327 "Host: www.google.com\r\n"
2328 "Connection: keep-alive\r\n\r\n"),
2329 };
2330
2331 MockRead data_reads1[] = {
2332 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2333 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2334 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422335 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232336 };
2337
2338 // Resend with authorization (username=foo, password=bar)
2339 MockWrite data_writes2[] = {
2340 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2341 "Host: www.google.com\r\n"
2342 "Connection: keep-alive\r\n"
2343 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2344 };
2345
2346 // Sever accepts the authorization.
2347 MockRead data_reads2[] = {
2348 MockRead("HTTP/1.0 200 OK\r\n"),
2349 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422350 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232351 };
2352
[email protected]69b43fe2009-06-15 09:47:372353 StaticMockSocket data1(data_reads1, data_writes1);
2354 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592355 session_deps.socket_factory.AddMockSocket(&data1);
2356 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232357
2358 TestCompletionCallback callback1;
2359
[email protected]684970b2009-08-14 04:54:462360 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422361 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232362
2363 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422364 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232365
[email protected]1c773ea12009-04-28 19:58:422366 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232367 EXPECT_FALSE(response == NULL);
2368
2369 // The password prompt info should have been set in
2370 // response->auth_challenge.
2371 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2372
[email protected]71e4573a2009-05-21 22:03:002373 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232374 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2375 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2376
2377 TestCompletionCallback callback2;
2378
2379 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422380 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232381
2382 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422383 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232384
2385 response = trans->GetResponseInfo();
2386 EXPECT_FALSE(response == NULL);
2387 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2388 EXPECT_EQ(100, response->headers->GetContentLength());
2389 }
2390
2391 // ------------------------------------------------------------------------
2392
2393 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2394 {
[email protected]5695b8c2009-09-30 21:36:432395 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232396
[email protected]1c773ea12009-04-28 19:58:422397 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232398 request.method = "GET";
2399 // Note that Transaction 1 was at /x/y/z, so this is in the same
2400 // protection space as MyRealm1.
2401 request.url = GURL("http://www.google.com/x/y/a/b");
2402 request.load_flags = 0;
2403
2404 MockWrite data_writes1[] = {
2405 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2406 "Host: www.google.com\r\n"
2407 "Connection: keep-alive\r\n"
2408 // Send preemptive authorization for MyRealm1
2409 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2410 };
2411
2412 // The server didn't like the preemptive authorization, and
2413 // challenges us for a different realm (MyRealm2).
2414 MockRead data_reads1[] = {
2415 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2416 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2417 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422418 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232419 };
2420
2421 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2422 MockWrite data_writes2[] = {
2423 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2424 "Host: www.google.com\r\n"
2425 "Connection: keep-alive\r\n"
2426 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2427 };
2428
2429 // Sever accepts the authorization.
2430 MockRead data_reads2[] = {
2431 MockRead("HTTP/1.0 200 OK\r\n"),
2432 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422433 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232434 };
2435
[email protected]69b43fe2009-06-15 09:47:372436 StaticMockSocket data1(data_reads1, data_writes1);
2437 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592438 session_deps.socket_factory.AddMockSocket(&data1);
2439 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232440
2441 TestCompletionCallback callback1;
2442
[email protected]684970b2009-08-14 04:54:462443 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422444 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232445
2446 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422447 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232448
[email protected]1c773ea12009-04-28 19:58:422449 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232450 EXPECT_FALSE(response == NULL);
2451
2452 // The password prompt info should have been set in
2453 // response->auth_challenge.
2454 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2455
[email protected]71e4573a2009-05-21 22:03:002456 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232457 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2458 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2459
2460 TestCompletionCallback callback2;
2461
2462 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422463 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232464
2465 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422466 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232467
2468 response = trans->GetResponseInfo();
2469 EXPECT_FALSE(response == NULL);
2470 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2471 EXPECT_EQ(100, response->headers->GetContentLength());
2472 }
2473
2474 // ------------------------------------------------------------------------
2475
2476 // Transaction 3: Resend a request in MyRealm's protection space --
2477 // succeed with preemptive authorization.
2478 {
[email protected]5695b8c2009-09-30 21:36:432479 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232480
[email protected]1c773ea12009-04-28 19:58:422481 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232482 request.method = "GET";
2483 request.url = GURL("http://www.google.com/x/y/z2");
2484 request.load_flags = 0;
2485
2486 MockWrite data_writes1[] = {
2487 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2488 "Host: www.google.com\r\n"
2489 "Connection: keep-alive\r\n"
2490 // The authorization for MyRealm1 gets sent preemptively
2491 // (since the url is in the same protection space)
2492 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2493 };
2494
2495 // Sever accepts the preemptive authorization
2496 MockRead data_reads1[] = {
2497 MockRead("HTTP/1.0 200 OK\r\n"),
2498 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422499 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232500 };
2501
[email protected]69b43fe2009-06-15 09:47:372502 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:592503 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f9ee6b52008-11-08 06:46:232504
2505 TestCompletionCallback callback1;
2506
[email protected]684970b2009-08-14 04:54:462507 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422508 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232509
2510 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422511 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232512
[email protected]1c773ea12009-04-28 19:58:422513 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232514 EXPECT_FALSE(response == NULL);
2515
2516 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2517 EXPECT_EQ(100, response->headers->GetContentLength());
2518 }
2519
2520 // ------------------------------------------------------------------------
2521
2522 // Transaction 4: request another URL in MyRealm (however the
2523 // url is not known to belong to the protection space, so no pre-auth).
2524 {
[email protected]5695b8c2009-09-30 21:36:432525 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232526
[email protected]1c773ea12009-04-28 19:58:422527 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232528 request.method = "GET";
2529 request.url = GURL("http://www.google.com/x/1");
2530 request.load_flags = 0;
2531
2532 MockWrite data_writes1[] = {
2533 MockWrite("GET /x/1 HTTP/1.1\r\n"
2534 "Host: www.google.com\r\n"
2535 "Connection: keep-alive\r\n\r\n"),
2536 };
2537
2538 MockRead data_reads1[] = {
2539 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2540 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2541 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422542 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232543 };
2544
2545 // Resend with authorization from MyRealm's cache.
2546 MockWrite data_writes2[] = {
2547 MockWrite("GET /x/1 HTTP/1.1\r\n"
2548 "Host: www.google.com\r\n"
2549 "Connection: keep-alive\r\n"
2550 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2551 };
2552
2553 // Sever accepts the authorization.
2554 MockRead data_reads2[] = {
2555 MockRead("HTTP/1.0 200 OK\r\n"),
2556 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422557 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232558 };
2559
[email protected]69b43fe2009-06-15 09:47:372560 StaticMockSocket data1(data_reads1, data_writes1);
2561 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592562 session_deps.socket_factory.AddMockSocket(&data1);
2563 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232564
2565 TestCompletionCallback callback1;
2566
[email protected]684970b2009-08-14 04:54:462567 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422568 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232569
2570 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422571 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232572
[email protected]0757e7702009-03-27 04:00:222573 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2574 TestCompletionCallback callback2;
2575 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422576 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222577 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422578 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222579 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2580
[email protected]1c773ea12009-04-28 19:58:422581 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232582 EXPECT_FALSE(response == NULL);
2583 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2584 EXPECT_EQ(100, response->headers->GetContentLength());
2585 }
2586
2587 // ------------------------------------------------------------------------
2588
2589 // Transaction 5: request a URL in MyRealm, but the server rejects the
2590 // cached identity. Should invalidate and re-prompt.
2591 {
[email protected]5695b8c2009-09-30 21:36:432592 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232593
[email protected]1c773ea12009-04-28 19:58:422594 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232595 request.method = "GET";
2596 request.url = GURL("http://www.google.com/p/q/t");
2597 request.load_flags = 0;
2598
2599 MockWrite data_writes1[] = {
2600 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2601 "Host: www.google.com\r\n"
2602 "Connection: keep-alive\r\n\r\n"),
2603 };
2604
2605 MockRead data_reads1[] = {
2606 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2607 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2608 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422609 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232610 };
2611
2612 // Resend with authorization from cache for MyRealm.
2613 MockWrite data_writes2[] = {
2614 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2615 "Host: www.google.com\r\n"
2616 "Connection: keep-alive\r\n"
2617 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2618 };
2619
2620 // Sever rejects the authorization.
2621 MockRead data_reads2[] = {
2622 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2623 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2624 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422625 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232626 };
2627
2628 // At this point we should prompt for new credentials for MyRealm.
2629 // Restart with username=foo3, password=foo4.
2630 MockWrite data_writes3[] = {
2631 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2632 "Host: www.google.com\r\n"
2633 "Connection: keep-alive\r\n"
2634 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2635 };
2636
2637 // Sever accepts the authorization.
2638 MockRead data_reads3[] = {
2639 MockRead("HTTP/1.0 200 OK\r\n"),
2640 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422641 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232642 };
2643
[email protected]69b43fe2009-06-15 09:47:372644 StaticMockSocket data1(data_reads1, data_writes1);
2645 StaticMockSocket data2(data_reads2, data_writes2);
2646 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:592647 session_deps.socket_factory.AddMockSocket(&data1);
2648 session_deps.socket_factory.AddMockSocket(&data2);
2649 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]f9ee6b52008-11-08 06:46:232650
2651 TestCompletionCallback callback1;
2652
[email protected]684970b2009-08-14 04:54:462653 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422654 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232655
2656 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422657 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232658
[email protected]0757e7702009-03-27 04:00:222659 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2660 TestCompletionCallback callback2;
2661 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422662 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222663 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422664 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222665 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2666
[email protected]1c773ea12009-04-28 19:58:422667 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232668 EXPECT_FALSE(response == NULL);
2669
2670 // The password prompt info should have been set in
2671 // response->auth_challenge.
2672 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2673
[email protected]71e4573a2009-05-21 22:03:002674 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232675 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2676 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2677
[email protected]0757e7702009-03-27 04:00:222678 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232679
[email protected]0757e7702009-03-27 04:00:222680 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422681 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232682
[email protected]0757e7702009-03-27 04:00:222683 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422684 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232685
2686 response = trans->GetResponseInfo();
2687 EXPECT_FALSE(response == NULL);
2688 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2689 EXPECT_EQ(100, response->headers->GetContentLength());
2690 }
2691}
[email protected]89ceba9a2009-03-21 03:46:062692
2693// Test the ResetStateForRestart() private method.
2694TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2695 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592696 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402697 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432698 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062699
2700 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062701 trans->read_buf_ = new IOBuffer(15);
2702 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572703 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062704
2705 // Setup state in response_
[email protected]0877e3d2009-10-17 22:29:572706 trans->http_stream_.reset(new HttpBasicStream(NULL));
2707 HttpResponseInfo* response = trans->http_stream_->GetResponseInfo();
2708 response->auth_challenge = new AuthChallengeInfo();
2709 response->ssl_info.cert_status = -15;
2710 response->response_time = base::Time::Now();
2711 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062712
2713 { // Setup state for response_.vary_data
2714 HttpRequestInfo request;
2715 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2716 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:572717 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]89ceba9a2009-03-21 03:46:062718 request.extra_headers = "Foo: 1\nbar: 23";
[email protected]0877e3d2009-10-17 22:29:572719 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:062720 }
2721
2722 // Cause the above state to be reset.
2723 trans->ResetStateForRestart();
2724
2725 // Verify that the state that needed to be reset, has been reset.
[email protected]0877e3d2009-10-17 22:29:572726 response = trans->http_stream_->GetResponseInfo();
[email protected]9b6fee12009-09-29 18:13:072727 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:062728 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:572729 EXPECT_EQ(0U, trans->request_headers_.size());
2730 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2731 EXPECT_TRUE(response->headers.get() == NULL);
2732 EXPECT_EQ(false, response->was_cached);
2733 EXPECT_EQ(0, response->ssl_info.cert_status);
2734 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:062735}
2736
[email protected]bacff652009-03-31 17:50:332737// Test HTTPS connections to a site with a bad certificate
2738TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592739 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402740 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432741 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332742
2743 HttpRequestInfo request;
2744 request.method = "GET";
2745 request.url = GURL("https://www.google.com/");
2746 request.load_flags = 0;
2747
2748 MockWrite data_writes[] = {
2749 MockWrite("GET / HTTP/1.1\r\n"
2750 "Host: www.google.com\r\n"
2751 "Connection: keep-alive\r\n\r\n"),
2752 };
2753
2754 MockRead data_reads[] = {
2755 MockRead("HTTP/1.0 200 OK\r\n"),
2756 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2757 MockRead("Content-Length: 100\r\n\r\n"),
2758 MockRead(false, OK),
2759 };
2760
[email protected]69b43fe2009-06-15 09:47:372761 StaticMockSocket ssl_bad_certificate;
2762 StaticMockSocket data(data_reads, data_writes);
[email protected]bacff652009-03-31 17:50:332763 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2764 MockSSLSocket ssl(true, OK);
2765
[email protected]228ff742009-06-05 01:19:592766 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2767 session_deps.socket_factory.AddMockSocket(&data);
2768 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2769 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332770
2771 TestCompletionCallback callback;
2772
[email protected]684970b2009-08-14 04:54:462773 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332774 EXPECT_EQ(ERR_IO_PENDING, rv);
2775
2776 rv = callback.WaitForResult();
2777 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2778
2779 rv = trans->RestartIgnoringLastError(&callback);
2780 EXPECT_EQ(ERR_IO_PENDING, rv);
2781
2782 rv = callback.WaitForResult();
2783 EXPECT_EQ(OK, rv);
2784
2785 const HttpResponseInfo* response = trans->GetResponseInfo();
2786
2787 EXPECT_FALSE(response == NULL);
2788 EXPECT_EQ(100, response->headers->GetContentLength());
2789}
2790
2791// Test HTTPS connections to a site with a bad certificate, going through a
2792// proxy
2793TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592794 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332795
2796 HttpRequestInfo request;
2797 request.method = "GET";
2798 request.url = GURL("https://www.google.com/");
2799 request.load_flags = 0;
2800
2801 MockWrite proxy_writes[] = {
2802 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452803 "Host: www.google.com\r\n"
2804 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332805 };
2806
2807 MockRead proxy_reads[] = {
2808 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422809 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:332810 };
2811
2812 MockWrite data_writes[] = {
2813 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452814 "Host: www.google.com\r\n"
2815 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332816 MockWrite("GET / HTTP/1.1\r\n"
2817 "Host: www.google.com\r\n"
2818 "Connection: keep-alive\r\n\r\n"),
2819 };
2820
2821 MockRead data_reads[] = {
2822 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
2823 MockRead("HTTP/1.0 200 OK\r\n"),
2824 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2825 MockRead("Content-Length: 100\r\n\r\n"),
2826 MockRead(false, OK),
2827 };
2828
[email protected]69b43fe2009-06-15 09:47:372829 StaticMockSocket ssl_bad_certificate(proxy_reads, proxy_writes);
2830 StaticMockSocket data(data_reads, data_writes);
[email protected]bacff652009-03-31 17:50:332831 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2832 MockSSLSocket ssl(true, OK);
2833
[email protected]228ff742009-06-05 01:19:592834 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2835 session_deps.socket_factory.AddMockSocket(&data);
2836 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2837 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332838
2839 TestCompletionCallback callback;
2840
2841 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:592842 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:332843
[email protected]d207a5f2009-06-04 05:28:402844 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432845 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332846
[email protected]684970b2009-08-14 04:54:462847 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332848 EXPECT_EQ(ERR_IO_PENDING, rv);
2849
2850 rv = callback.WaitForResult();
2851 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2852
2853 rv = trans->RestartIgnoringLastError(&callback);
2854 EXPECT_EQ(ERR_IO_PENDING, rv);
2855
2856 rv = callback.WaitForResult();
2857 EXPECT_EQ(OK, rv);
2858
2859 const HttpResponseInfo* response = trans->GetResponseInfo();
2860
2861 EXPECT_FALSE(response == NULL);
2862 EXPECT_EQ(100, response->headers->GetContentLength());
2863 }
2864}
2865
[email protected]1c773ea12009-04-28 19:58:422866TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:592867 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402868 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432869 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:422870
2871 HttpRequestInfo request;
2872 request.method = "GET";
2873 request.url = GURL("http://www.google.com/");
2874 request.user_agent = "Chromium Ultra Awesome X Edition";
2875
2876 MockWrite data_writes[] = {
2877 MockWrite("GET / HTTP/1.1\r\n"
2878 "Host: www.google.com\r\n"
2879 "Connection: keep-alive\r\n"
2880 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
2881 };
2882
2883 // Lastly, the server responds with the actual content.
2884 MockRead data_reads[] = {
2885 MockRead("HTTP/1.0 200 OK\r\n"),
2886 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2887 MockRead("Content-Length: 100\r\n\r\n"),
2888 MockRead(false, OK),
2889 };
2890
[email protected]69b43fe2009-06-15 09:47:372891 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592892 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422893
2894 TestCompletionCallback callback;
2895
[email protected]684970b2009-08-14 04:54:462896 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422897 EXPECT_EQ(ERR_IO_PENDING, rv);
2898
2899 rv = callback.WaitForResult();
2900 EXPECT_EQ(OK, rv);
2901}
2902
2903TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:592904 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402905 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432906 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:422907
2908 HttpRequestInfo request;
2909 request.method = "GET";
2910 request.url = GURL("http://www.google.com/");
2911 request.load_flags = 0;
2912 request.referrer = GURL("http://the.previous.site.com/");
2913
2914 MockWrite data_writes[] = {
2915 MockWrite("GET / HTTP/1.1\r\n"
2916 "Host: www.google.com\r\n"
2917 "Connection: keep-alive\r\n"
2918 "Referer: http://the.previous.site.com/\r\n\r\n"),
2919 };
2920
2921 // Lastly, the server responds with the actual content.
2922 MockRead data_reads[] = {
2923 MockRead("HTTP/1.0 200 OK\r\n"),
2924 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2925 MockRead("Content-Length: 100\r\n\r\n"),
2926 MockRead(false, OK),
2927 };
2928
[email protected]69b43fe2009-06-15 09:47:372929 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592930 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422931
2932 TestCompletionCallback callback;
2933
[email protected]684970b2009-08-14 04:54:462934 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422935 EXPECT_EQ(ERR_IO_PENDING, rv);
2936
2937 rv = callback.WaitForResult();
2938 EXPECT_EQ(OK, rv);
2939}
2940
2941TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592942 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402943 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432944 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:422945
2946 HttpRequestInfo request;
2947 request.method = "POST";
2948 request.url = GURL("http://www.google.com/");
2949
2950 MockWrite data_writes[] = {
2951 MockWrite("POST / HTTP/1.1\r\n"
2952 "Host: www.google.com\r\n"
2953 "Connection: keep-alive\r\n"
2954 "Content-Length: 0\r\n\r\n"),
2955 };
2956
2957 // Lastly, the server responds with the actual content.
2958 MockRead data_reads[] = {
2959 MockRead("HTTP/1.0 200 OK\r\n"),
2960 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2961 MockRead("Content-Length: 100\r\n\r\n"),
2962 MockRead(false, OK),
2963 };
2964
[email protected]69b43fe2009-06-15 09:47:372965 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592966 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422967
2968 TestCompletionCallback callback;
2969
[email protected]684970b2009-08-14 04:54:462970 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422971 EXPECT_EQ(ERR_IO_PENDING, rv);
2972
2973 rv = callback.WaitForResult();
2974 EXPECT_EQ(OK, rv);
2975}
2976
2977TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592978 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402979 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432980 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:422981
2982 HttpRequestInfo request;
2983 request.method = "PUT";
2984 request.url = GURL("http://www.google.com/");
2985
2986 MockWrite data_writes[] = {
2987 MockWrite("PUT / HTTP/1.1\r\n"
2988 "Host: www.google.com\r\n"
2989 "Connection: keep-alive\r\n"
2990 "Content-Length: 0\r\n\r\n"),
2991 };
2992
2993 // Lastly, the server responds with the actual content.
2994 MockRead data_reads[] = {
2995 MockRead("HTTP/1.0 200 OK\r\n"),
2996 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2997 MockRead("Content-Length: 100\r\n\r\n"),
2998 MockRead(false, OK),
2999 };
3000
[email protected]69b43fe2009-06-15 09:47:373001 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593002 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423003
3004 TestCompletionCallback callback;
3005
[email protected]684970b2009-08-14 04:54:463006 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423007 EXPECT_EQ(ERR_IO_PENDING, rv);
3008
3009 rv = callback.WaitForResult();
3010 EXPECT_EQ(OK, rv);
3011}
3012
3013TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593014 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403015 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433016 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423017
3018 HttpRequestInfo request;
3019 request.method = "HEAD";
3020 request.url = GURL("http://www.google.com/");
3021
3022 MockWrite data_writes[] = {
3023 MockWrite("HEAD / HTTP/1.1\r\n"
3024 "Host: www.google.com\r\n"
3025 "Connection: keep-alive\r\n"
3026 "Content-Length: 0\r\n\r\n"),
3027 };
3028
3029 // Lastly, the server responds with the actual content.
3030 MockRead data_reads[] = {
3031 MockRead("HTTP/1.0 200 OK\r\n"),
3032 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3033 MockRead("Content-Length: 100\r\n\r\n"),
3034 MockRead(false, OK),
3035 };
3036
[email protected]69b43fe2009-06-15 09:47:373037 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593038 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423039
3040 TestCompletionCallback callback;
3041
[email protected]684970b2009-08-14 04:54:463042 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423043 EXPECT_EQ(ERR_IO_PENDING, rv);
3044
3045 rv = callback.WaitForResult();
3046 EXPECT_EQ(OK, rv);
3047}
3048
3049TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593050 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403051 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433052 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423053
3054 HttpRequestInfo request;
3055 request.method = "GET";
3056 request.url = GURL("http://www.google.com/");
3057 request.load_flags = LOAD_BYPASS_CACHE;
3058
3059 MockWrite data_writes[] = {
3060 MockWrite("GET / HTTP/1.1\r\n"
3061 "Host: www.google.com\r\n"
3062 "Connection: keep-alive\r\n"
3063 "Pragma: no-cache\r\n"
3064 "Cache-Control: no-cache\r\n\r\n"),
3065 };
3066
3067 // Lastly, the server responds with the actual content.
3068 MockRead data_reads[] = {
3069 MockRead("HTTP/1.0 200 OK\r\n"),
3070 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3071 MockRead("Content-Length: 100\r\n\r\n"),
3072 MockRead(false, OK),
3073 };
3074
[email protected]69b43fe2009-06-15 09:47:373075 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593076 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423077
3078 TestCompletionCallback callback;
3079
[email protected]684970b2009-08-14 04:54:463080 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423081 EXPECT_EQ(ERR_IO_PENDING, rv);
3082
3083 rv = callback.WaitForResult();
3084 EXPECT_EQ(OK, rv);
3085}
3086
3087TEST_F(HttpNetworkTransactionTest,
3088 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593089 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403090 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433091 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423092
3093 HttpRequestInfo request;
3094 request.method = "GET";
3095 request.url = GURL("http://www.google.com/");
3096 request.load_flags = LOAD_VALIDATE_CACHE;
3097
3098 MockWrite data_writes[] = {
3099 MockWrite("GET / HTTP/1.1\r\n"
3100 "Host: www.google.com\r\n"
3101 "Connection: keep-alive\r\n"
3102 "Cache-Control: max-age=0\r\n\r\n"),
3103 };
3104
3105 // Lastly, the server responds with the actual content.
3106 MockRead data_reads[] = {
3107 MockRead("HTTP/1.0 200 OK\r\n"),
3108 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3109 MockRead("Content-Length: 100\r\n\r\n"),
3110 MockRead(false, OK),
3111 };
3112
[email protected]69b43fe2009-06-15 09:47:373113 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593114 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423115
3116 TestCompletionCallback callback;
3117
[email protected]684970b2009-08-14 04:54:463118 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423119 EXPECT_EQ(ERR_IO_PENDING, rv);
3120
3121 rv = callback.WaitForResult();
3122 EXPECT_EQ(OK, rv);
3123}
3124
3125TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593126 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403127 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433128 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423129
3130 HttpRequestInfo request;
3131 request.method = "GET";
3132 request.url = GURL("http://www.google.com/");
3133 request.extra_headers = "FooHeader: Bar\r\n";
3134
3135 MockWrite data_writes[] = {
3136 MockWrite("GET / HTTP/1.1\r\n"
3137 "Host: www.google.com\r\n"
3138 "Connection: keep-alive\r\n"
3139 "FooHeader: Bar\r\n\r\n"),
3140 };
3141
3142 // Lastly, the server responds with the actual content.
3143 MockRead data_reads[] = {
3144 MockRead("HTTP/1.0 200 OK\r\n"),
3145 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3146 MockRead("Content-Length: 100\r\n\r\n"),
3147 MockRead(false, OK),
3148 };
3149
[email protected]69b43fe2009-06-15 09:47:373150 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593151 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423152
3153 TestCompletionCallback callback;
3154
[email protected]684970b2009-08-14 04:54:463155 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423156 EXPECT_EQ(ERR_IO_PENDING, rv);
3157
3158 rv = callback.WaitForResult();
3159 EXPECT_EQ(OK, rv);
3160}
3161
[email protected]3cd17242009-06-23 02:59:023162TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093163 SessionDependencies session_deps(
3164 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023165
3166 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433167 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023168
3169 HttpRequestInfo request;
3170 request.method = "GET";
3171 request.url = GURL("http://www.google.com/");
3172 request.load_flags = 0;
3173
3174 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3175 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3176
3177 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353178 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023179 MockWrite("GET / HTTP/1.1\r\n"
3180 "Host: www.google.com\r\n"
3181 "Connection: keep-alive\r\n\r\n")
3182 };
3183
3184 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353185 MockWrite(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023186 MockRead("HTTP/1.0 200 OK\r\n"),
3187 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3188 MockRead("Payload"),
3189 MockRead(false, OK)
3190 };
3191
3192 StaticMockSocket data(data_reads, data_writes);
3193 session_deps.socket_factory.AddMockSocket(&data);
3194
3195 TestCompletionCallback callback;
3196
[email protected]684970b2009-08-14 04:54:463197 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023198 EXPECT_EQ(ERR_IO_PENDING, rv);
3199
3200 rv = callback.WaitForResult();
3201 EXPECT_EQ(OK, rv);
3202
3203 const HttpResponseInfo* response = trans->GetResponseInfo();
3204 EXPECT_FALSE(response == NULL);
3205
3206 std::string response_text;
3207 rv = ReadTransaction(trans.get(), &response_text);
3208 EXPECT_EQ(OK, rv);
3209 EXPECT_EQ("Payload", response_text);
3210}
3211
3212TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093213 SessionDependencies session_deps(
3214 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023215
3216 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433217 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023218
3219 HttpRequestInfo request;
3220 request.method = "GET";
3221 request.url = GURL("https://www.google.com/");
3222 request.load_flags = 0;
3223
3224 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3225 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3226
3227 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353228 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3229 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023230 MockWrite("GET / HTTP/1.1\r\n"
3231 "Host: www.google.com\r\n"
3232 "Connection: keep-alive\r\n\r\n")
3233 };
3234
3235 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353236 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3237 arraysize(read_buffer)),
3238 MockRead("HTTP/1.0 200 OK\r\n"),
3239 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3240 MockRead("Payload"),
3241 MockRead(false, OK)
3242 };
3243
3244 StaticMockSocket data(data_reads, data_writes);
3245 session_deps.socket_factory.AddMockSocket(&data);
3246
3247 MockSSLSocket ssl(true, OK);
3248 session_deps.socket_factory.AddMockSSLSocket(&ssl);
3249
3250 TestCompletionCallback callback;
3251
[email protected]684970b2009-08-14 04:54:463252 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353253 EXPECT_EQ(ERR_IO_PENDING, rv);
3254
3255 rv = callback.WaitForResult();
3256 EXPECT_EQ(OK, rv);
3257
3258 const HttpResponseInfo* response = trans->GetResponseInfo();
3259 EXPECT_FALSE(response == NULL);
3260
3261 std::string response_text;
3262 rv = ReadTransaction(trans.get(), &response_text);
3263 EXPECT_EQ(OK, rv);
3264 EXPECT_EQ("Payload", response_text);
3265}
3266
3267TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093268 SessionDependencies session_deps(
3269 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353270
3271 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433272 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353273
3274 HttpRequestInfo request;
3275 request.method = "GET";
3276 request.url = GURL("http://www.google.com/");
3277 request.load_flags = 0;
3278
3279 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3280 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3281 const char kSOCKS5OkRequest[] =
3282 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3283 const char kSOCKS5OkResponse[] =
3284 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3285
3286 MockWrite data_writes[] = {
3287 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3288 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3289 MockWrite("GET / HTTP/1.1\r\n"
3290 "Host: www.google.com\r\n"
3291 "Connection: keep-alive\r\n\r\n")
3292 };
3293
3294 MockRead data_reads[] = {
3295 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3296 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3297 MockRead("HTTP/1.0 200 OK\r\n"),
3298 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3299 MockRead("Payload"),
3300 MockRead(false, OK)
3301 };
3302
3303 StaticMockSocket data(data_reads, data_writes);
3304 session_deps.socket_factory.AddMockSocket(&data);
3305
3306 TestCompletionCallback callback;
3307
[email protected]684970b2009-08-14 04:54:463308 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353309 EXPECT_EQ(ERR_IO_PENDING, rv);
3310
3311 rv = callback.WaitForResult();
3312 EXPECT_EQ(OK, rv);
3313
3314 const HttpResponseInfo* response = trans->GetResponseInfo();
3315 EXPECT_FALSE(response == NULL);
3316
3317 std::string response_text;
3318 rv = ReadTransaction(trans.get(), &response_text);
3319 EXPECT_EQ(OK, rv);
3320 EXPECT_EQ("Payload", response_text);
3321}
3322
3323TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093324 SessionDependencies session_deps(
3325 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353326
3327 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433328 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353329
3330 HttpRequestInfo request;
3331 request.method = "GET";
3332 request.url = GURL("https://www.google.com/");
3333 request.load_flags = 0;
3334
3335 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3336 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3337 const unsigned char kSOCKS5OkRequest[] =
3338 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x01, 0xBB };
3339 const char kSOCKS5OkResponse[] =
3340 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3341
3342 MockWrite data_writes[] = {
3343 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3344 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3345 arraysize(kSOCKS5OkRequest)),
3346 MockWrite("GET / HTTP/1.1\r\n"
3347 "Host: www.google.com\r\n"
3348 "Connection: keep-alive\r\n\r\n")
3349 };
3350
3351 MockRead data_reads[] = {
3352 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3353 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023354 MockRead("HTTP/1.0 200 OK\r\n"),
3355 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3356 MockRead("Payload"),
3357 MockRead(false, OK)
3358 };
3359
3360 StaticMockSocket data(data_reads, data_writes);
3361 session_deps.socket_factory.AddMockSocket(&data);
3362
3363 MockSSLSocket ssl(true, OK);
3364 session_deps.socket_factory.AddMockSSLSocket(&ssl);
3365
3366 TestCompletionCallback callback;
3367
[email protected]684970b2009-08-14 04:54:463368 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023369 EXPECT_EQ(ERR_IO_PENDING, rv);
3370
3371 rv = callback.WaitForResult();
3372 EXPECT_EQ(OK, rv);
3373
3374 const HttpResponseInfo* response = trans->GetResponseInfo();
3375 EXPECT_FALSE(response == NULL);
3376
3377 std::string response_text;
3378 rv = ReadTransaction(trans.get(), &response_text);
3379 EXPECT_EQ(OK, rv);
3380 EXPECT_EQ("Payload", response_text);
3381}
3382
[email protected]04e5be32009-06-26 20:00:313383// Tests that for connection endpoints the group names are correctly set.
3384TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3385 const struct {
3386 const std::string proxy_server;
3387 const std::string url;
3388 const std::string expected_group_name;
3389 } tests[] = {
3390 {
3391 "", // no proxy (direct)
3392 "http://www.google.com/direct",
3393 "http://www.google.com/",
3394 },
3395 {
3396 "http_proxy",
3397 "http://www.google.com/http_proxy_normal",
3398 "proxy/http_proxy:80/",
3399 },
3400 {
3401 "socks4://socks_proxy:1080",
3402 "http://www.google.com/socks4_direct",
3403 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3404 },
3405
3406 // SSL Tests
3407 {
3408 "",
3409 "https://www.google.com/direct_ssl",
3410 "https://www.google.com/",
3411 },
3412 {
3413 "http_proxy",
3414 "https://www.google.com/http_connect_ssl",
3415 "proxy/http_proxy:80/https://www.google.com/",
3416 },
3417 {
3418 "socks4://socks_proxy:1080",
3419 "https://www.google.com/socks4_ssl",
3420 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3421 },
3422 };
3423
3424 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093425 SessionDependencies session_deps(
3426 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313427
3428 scoped_refptr<CaptureGroupNameSocketPool> conn_pool(
3429 new CaptureGroupNameSocketPool());
3430
3431 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a937a06d2009-08-19 21:19:243432 session->tcp_socket_pool_ = conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313433
[email protected]5695b8c2009-09-30 21:36:433434 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313435
3436 HttpRequestInfo request;
3437 request.method = "GET";
3438 request.url = GURL(tests[i].url);
3439 request.load_flags = 0;
3440
3441 TestCompletionCallback callback;
3442
3443 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463444 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]04e5be32009-06-26 20:00:313445 EXPECT_EQ(tests[i].expected_group_name,
3446 conn_pool->last_group_name_received());
3447 }
3448}
3449
[email protected]9172a982009-06-06 00:30:253450TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543451 SessionDependencies session_deps(
3452 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323453
3454 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3455
[email protected]9172a982009-06-06 00:30:253456 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433457 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253458
3459 HttpRequestInfo request;
3460 request.method = "GET";
3461 request.url = GURL("http://www.google.com/");
3462
3463 TestCompletionCallback callback;
3464
[email protected]684970b2009-08-14 04:54:463465 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253466 EXPECT_EQ(ERR_IO_PENDING, rv);
3467
[email protected]9172a982009-06-06 00:30:253468 rv = callback.WaitForResult();
3469 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3470}
3471
[email protected]f3e6c1e2009-06-15 20:52:123472// Host resolution observer used by
3473// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3474// resovle requests are issued with a referrer of |expected_referrer|.
3475class ResolutionReferrerObserver : public HostResolver::Observer {
3476 public:
3477 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3478 : expected_referrer_(expected_referrer),
3479 called_start_with_referrer_(false),
3480 called_finish_with_referrer_(false) {
3481 }
3482
3483 virtual void OnStartResolution(int id,
3484 const HostResolver::RequestInfo& info) {
3485 if (info.referrer() == expected_referrer_)
3486 called_start_with_referrer_ = true;
3487 }
3488
3489 virtual void OnFinishResolutionWithStatus(
3490 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3491 if (info.referrer() == expected_referrer_)
3492 called_finish_with_referrer_ = true;
3493 }
3494
[email protected]eb255d32009-06-17 02:11:033495 virtual void OnCancelResolution(int id,
3496 const HostResolver::RequestInfo& info ) {
3497 FAIL() << "Should not be cancelling any requests!";
3498 }
3499
[email protected]f3e6c1e2009-06-15 20:52:123500 bool did_complete_with_expected_referrer() const {
3501 return called_start_with_referrer_ && called_finish_with_referrer_;
3502 }
3503
3504 private:
3505 GURL expected_referrer_;
3506 bool called_start_with_referrer_;
3507 bool called_finish_with_referrer_;
3508
3509 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3510};
3511
3512// Make sure that when HostResolver::Resolve() is invoked, it passes through
3513// the "referrer". This is depended on by the DNS prefetch observer.
3514TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3515 GURL referrer = GURL("http://expected-referrer/");
3516 EXPECT_TRUE(referrer.is_valid());
3517 ResolutionReferrerObserver resolution_observer(referrer);
3518
3519 SessionDependencies session_deps;
3520 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433521 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123522
3523 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143524 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123525
3526 // Connect up a mock socket which will fail when reading.
3527 MockRead data_reads[] = {
3528 MockRead(false, ERR_FAILED),
3529 };
3530 StaticMockSocket data(data_reads, NULL);
3531 session_deps.socket_factory.AddMockSocket(&data);
3532
3533 // Issue a request, containing an HTTP referrer.
3534 HttpRequestInfo request;
3535 request.method = "GET";
3536 request.referrer = referrer;
3537 request.url = GURL("http://www.google.com/");
3538
3539 // Run the request until it fails reading from the socket.
3540 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463541 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123542 EXPECT_EQ(ERR_IO_PENDING, rv);
3543 rv = callback.WaitForResult();
3544 EXPECT_EQ(ERR_FAILED, rv);
3545
3546 // Check that the host resolution observer saw |referrer|.
3547 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3548}
3549
[email protected]3b9cca42009-06-16 01:08:283550// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3551// host cache is bypassed.
3552TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3553 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323554
[email protected]a2c2fb92009-07-18 07:31:043555 // Select a host resolver that does caching.
3556 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323557
[email protected]3b9cca42009-06-16 01:08:283558 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433559 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:283560
3561 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3562 // a synchronous lookup.)
3563 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143564 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463565 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3566 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283567 EXPECT_EQ(OK, rv);
3568
3569 // Verify that it was added to host cache, by doing a subsequent async lookup
3570 // and confirming it completes synchronously.
3571 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463572 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283573 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463574 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323575 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283576
3577 // Inject a failure the next time that "www.google.com" is resolved. This way
3578 // we can tell if the next lookup hit the cache, or the "network".
3579 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323580 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283581
3582 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3583 // first read -- this won't be reached as the host resolution will fail first.
3584 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
3585 StaticMockSocket data(data_reads, NULL);
3586 session_deps.socket_factory.AddMockSocket(&data);
3587
3588 // Issue a request, asking to bypass the cache(s).
3589 HttpRequestInfo request;
3590 request.method = "GET";
3591 request.load_flags = LOAD_BYPASS_CACHE;
3592 request.url = GURL("http://www.google.com/");
3593
3594 // Run the request.
3595 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463596 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283597 ASSERT_EQ(ERR_IO_PENDING, rv);
3598 rv = callback.WaitForResult();
3599
3600 // If we bypassed the cache, we would have gotten a failure while resolving
3601 // "www.google.com".
3602 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3603}
3604
[email protected]0877e3d2009-10-17 22:29:573605// Make sure we can handle an error when writing the request.
3606TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3607 SessionDependencies session_deps;
3608 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3609
3610 HttpRequestInfo request;
3611 request.method = "GET";
3612 request.url = GURL("http://www.foo.com/");
3613 request.load_flags = 0;
3614
3615 MockWrite write_failure[] = {
3616 MockWrite(true, ERR_CONNECTION_RESET),
3617 };
3618 StaticMockSocket data(NULL, write_failure);
3619 session_deps.socket_factory.AddMockSocket(&data);
3620
3621 TestCompletionCallback callback;
3622
3623 scoped_ptr<HttpTransaction> trans(
3624 new HttpNetworkTransaction(CreateSession(&session_deps)));
3625
3626 int rv = trans->Start(&request, &callback, NULL);
3627 EXPECT_EQ(ERR_IO_PENDING, rv);
3628
3629 rv = callback.WaitForResult();
3630 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3631}
3632
3633// Check that a connection closed after the start of the headers finishes ok.
3634TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3635 SessionDependencies session_deps;
3636 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3637
3638 HttpRequestInfo request;
3639 request.method = "GET";
3640 request.url = GURL("http://www.foo.com/");
3641 request.load_flags = 0;
3642
3643 MockRead data_reads[] = {
3644 MockRead("HTTP/1."),
3645 MockRead(false, OK),
3646 };
3647
3648 StaticMockSocket data(data_reads, NULL);
3649 session_deps.socket_factory.AddMockSocket(&data);
3650
3651 TestCompletionCallback callback;
3652
3653 scoped_ptr<HttpTransaction> trans(
3654 new HttpNetworkTransaction(CreateSession(&session_deps)));
3655
3656 int rv = trans->Start(&request, &callback, NULL);
3657 EXPECT_EQ(ERR_IO_PENDING, rv);
3658
3659 rv = callback.WaitForResult();
3660 EXPECT_EQ(OK, rv);
3661
3662 const HttpResponseInfo* response = trans->GetResponseInfo();
3663 EXPECT_TRUE(response != NULL);
3664
3665 EXPECT_TRUE(response->headers != NULL);
3666 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
3667
3668 std::string response_data;
3669 rv = ReadTransaction(trans.get(), &response_data);
3670 EXPECT_EQ(OK, rv);
3671 EXPECT_EQ("", response_data);
3672}
3673
3674// Make sure that a dropped connection while draining the body for auth
3675// restart does the right thing.
3676TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
3677 SessionDependencies session_deps;
3678 scoped_ptr<HttpTransaction> trans(
3679 new HttpNetworkTransaction(CreateSession(&session_deps)));
3680
3681 HttpRequestInfo request;
3682 request.method = "GET";
3683 request.url = GURL("http://www.google.com/");
3684 request.load_flags = 0;
3685
3686 MockWrite data_writes1[] = {
3687 MockWrite("GET / HTTP/1.1\r\n"
3688 "Host: www.google.com\r\n"
3689 "Connection: keep-alive\r\n\r\n"),
3690 };
3691
3692 MockRead data_reads1[] = {
3693 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3694 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3695 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3696 MockRead("Content-Length: 14\r\n\r\n"),
3697 MockRead("Unauth"),
3698 MockRead(true, ERR_CONNECTION_RESET),
3699 };
3700
3701 StaticMockSocket data1(data_reads1, data_writes1);
3702 session_deps.socket_factory.AddMockSocket(&data1);
3703
3704 // After calling trans->RestartWithAuth(), this is the request we should
3705 // be issuing -- the final header line contains the credentials.
3706 MockWrite data_writes2[] = {
3707 MockWrite("GET / HTTP/1.1\r\n"
3708 "Host: www.google.com\r\n"
3709 "Connection: keep-alive\r\n"
3710 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3711 };
3712
3713 // Lastly, the server responds with the actual content.
3714 MockRead data_reads2[] = {
3715 MockRead("HTTP/1.1 200 OK\r\n"),
3716 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3717 MockRead("Content-Length: 100\r\n\r\n"),
3718 MockRead(false, OK),
3719 };
3720
3721 StaticMockSocket data2(data_reads2, data_writes2);
3722 session_deps.socket_factory.AddMockSocket(&data2);
3723
3724 TestCompletionCallback callback1;
3725
3726 int rv = trans->Start(&request, &callback1, NULL);
3727 EXPECT_EQ(ERR_IO_PENDING, rv);
3728
3729 rv = callback1.WaitForResult();
3730 EXPECT_EQ(OK, rv);
3731
3732 const HttpResponseInfo* response = trans->GetResponseInfo();
3733 EXPECT_FALSE(response == NULL);
3734
3735 // The password prompt info should have been set in response->auth_challenge.
3736 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3737
3738 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3739 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3740 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3741
3742 TestCompletionCallback callback2;
3743
3744 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3745 EXPECT_EQ(ERR_IO_PENDING, rv);
3746
3747 rv = callback2.WaitForResult();
3748 EXPECT_EQ(OK, rv);
3749
3750 response = trans->GetResponseInfo();
3751 EXPECT_FALSE(response == NULL);
3752 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3753 EXPECT_EQ(100, response->headers->GetContentLength());
3754}
3755
3756// Test HTTPS connections going through a proxy that sends extra data.
3757TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
3758 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
3759
3760 HttpRequestInfo request;
3761 request.method = "GET";
3762 request.url = GURL("https://www.google.com/");
3763 request.load_flags = 0;
3764
3765 MockRead proxy_reads[] = {
3766 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
3767 MockRead(false, OK)
3768 };
3769
3770 StaticMockSocket data(proxy_reads, NULL);
3771 MockSSLSocket ssl(true, OK);
3772
3773 session_deps.socket_factory.AddMockSocket(&data);
3774 session_deps.socket_factory.AddMockSSLSocket(&ssl);
3775
3776 TestCompletionCallback callback;
3777
3778 session_deps.socket_factory.ResetNextMockIndexes();
3779
3780 scoped_ptr<HttpTransaction> trans(
3781 new HttpNetworkTransaction(CreateSession(&session_deps)));
3782
3783 int rv = trans->Start(&request, &callback, NULL);
3784 EXPECT_EQ(ERR_IO_PENDING, rv);
3785
3786 rv = callback.WaitForResult();
3787 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3788}
3789
[email protected]89ceba9a2009-03-21 03:46:063790} // namespace net