blob: f12fd1ffb27f4e7e2dc8253241e5e96f27b1e90a [file] [log] [blame]
[email protected]9b6fee12009-09-29 18:13:071// Copyright (c) 2009 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]77848d12008-11-14 00:00:225#include <math.h> // ceil
6
[email protected]68bf9152008-09-25 19:47:307#include "base/compiler_specific.h"
[email protected]bacff652009-03-31 17:50:338#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:329#include "net/base/mock_host_resolver.h"
[email protected]db36938c2009-08-19 21:48:4210#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3311#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5212#include "net/base/test_completion_callback.h"
13#include "net/base/upload_data.h"
[email protected]d1eda932009-11-04 01:03:1014#include "net/flip/flip_session_pool.h"
[email protected]385a4672009-03-11 22:21:2915#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5716#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5217#include "net/http/http_network_session.h"
18#include "net/http/http_network_transaction.h"
[email protected]0877e3d2009-10-17 22:29:5719#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5220#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5321#include "net/proxy/proxy_config_service_fixed.h"
[email protected]f7984fc62009-06-22 23:26:4422#include "net/socket/client_socket_factory.h"
23#include "net/socket/socket_test_util.h"
24#include "net/socket/ssl_client_socket.h"
initial.commit586acc5fe2008-07-26 22:42:5225#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1526#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5227
28//-----------------------------------------------------------------------------
29
[email protected]89ceba9a2009-03-21 03:46:0630namespace net {
31
[email protected]db8f44c2008-12-13 04:52:0132// Create a proxy service which fails on all requests (falls back to direct).
[email protected]1c773ea12009-04-28 19:58:4233ProxyService* CreateNullProxyService() {
34 return ProxyService::CreateNull();
initial.commit586acc5fe2008-07-26 22:42:5235}
36
[email protected]e44de5d2009-06-05 20:12:4537// Helper to manage the lifetimes of the dependencies for a
38// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5939class SessionDependencies {
40 public:
41 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4242 SessionDependencies()
43 : host_resolver(new MockHostResolver),
44 proxy_service(CreateNullProxyService()),
[email protected]d1eda932009-11-04 01:03:1045 ssl_config_service(new SSLConfigServiceDefaults),
46 flip_session_pool(new FlipSessionPool) {}
[email protected]228ff742009-06-05 01:19:5947
48 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4549 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4250 : host_resolver(new MockHostResolver),
51 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1052 ssl_config_service(new SSLConfigServiceDefaults),
53 flip_session_pool(new FlipSessionPool) {}
[email protected]228ff742009-06-05 01:19:5954
[email protected]a2c2fb92009-07-18 07:31:0455 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0956 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4257 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5958 MockClientSocketFactory socket_factory;
[email protected]d1eda932009-11-04 01:03:1059 scoped_refptr<FlipSessionPool> flip_session_pool;
[email protected]228ff742009-06-05 01:19:5960};
61
[email protected]1c773ea12009-04-28 19:58:4262ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5063 net::ProxyConfig proxy_config;
64 proxy_config.proxy_rules.ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3965 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5366}
67
68
[email protected]228ff742009-06-05 01:19:5969HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]94a0d3d92009-06-27 01:50:1470 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:0971 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:4272 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:1073 session_deps->ssl_config_service,
74 session_deps->flip_session_pool);
[email protected]e8d536192008-10-17 22:21:1475}
76
[email protected]89836e22008-09-25 20:33:4277class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:5278 public:
[email protected]0e75a732008-10-16 20:36:0979 virtual void TearDown() {
80 // Empty the current queue.
81 MessageLoop::current()->RunAllPending();
82 PlatformTest::TearDown();
83 }
84
[email protected]3d2a59b2008-09-26 19:44:2585 protected:
86 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:5287
[email protected]ff007e162009-05-23 09:13:1588 struct SimpleGetHelperResult {
89 int rv;
90 std::string status_line;
91 std::string response_data;
92 };
initial.commit586acc5fe2008-07-26 22:42:5293
[email protected]ff007e162009-05-23 09:13:1594 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
95 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:5296
[email protected]228ff742009-06-05 01:19:5997 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:4098 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:4399 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52100
[email protected]ff007e162009-05-23 09:13:15101 HttpRequestInfo request;
102 request.method = "GET";
103 request.url = GURL("http://www.google.com/");
104 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52105
[email protected]5ecc992a42009-11-11 01:41:59106 StaticSocketDataProvider data(data_reads, NULL);
107 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52108
[email protected]ff007e162009-05-23 09:13:15109 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52110
[email protected]684970b2009-08-14 04:54:46111 int rv = trans->Start(&request, &callback, NULL);
[email protected]ff007e162009-05-23 09:13:15112 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52113
[email protected]ff007e162009-05-23 09:13:15114 out.rv = callback.WaitForResult();
115 if (out.rv != OK)
116 return out;
117
118 const HttpResponseInfo* response = trans->GetResponseInfo();
119 EXPECT_TRUE(response != NULL);
120
121 EXPECT_TRUE(response->headers != NULL);
122 out.status_line = response->headers->GetStatusLine();
123
124 rv = ReadTransaction(trans.get(), &out.response_data);
125 EXPECT_EQ(OK, rv);
126
[email protected]aecfbf22008-10-16 02:02:47127 return out;
[email protected]ff007e162009-05-23 09:13:15128 }
initial.commit586acc5fe2008-07-26 22:42:52129
[email protected]ff007e162009-05-23 09:13:15130 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
131 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52132
[email protected]ff007e162009-05-23 09:13:15133 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15134};
[email protected]231d5a32008-09-13 00:45:27135
[email protected]15a5ccf82008-10-23 19:57:43136// Fill |str| with a long header list that consumes >= |size| bytes.
137void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19138 const char* row =
139 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
140 const int sizeof_row = strlen(row);
141 const int num_rows = static_cast<int>(
142 ceil(static_cast<float>(size) / sizeof_row));
143 const int sizeof_data = num_rows * sizeof_row;
144 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43145 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51146
[email protected]4ddaf2502008-10-23 18:26:19147 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43148 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19149}
150
[email protected]385a4672009-03-11 22:21:29151// Alternative functions that eliminate randomness and dependency on the local
152// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20153void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29154 static const uint8 bytes[] = {
155 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
156 };
157 static size_t current_byte = 0;
158 for (size_t i = 0; i < n; ++i) {
159 output[i] = bytes[current_byte++];
160 current_byte %= arraysize(bytes);
161 }
162}
163
[email protected]fe2bc6a2009-03-23 16:52:20164void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29165 static const uint8 bytes[] = {
166 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
167 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
168 };
169 static size_t current_byte = 0;
170 for (size_t i = 0; i < n; ++i) {
171 output[i] = bytes[current_byte++];
172 current_byte %= arraysize(bytes);
173 }
174}
175
[email protected]fe2bc6a2009-03-23 16:52:20176std::string MockGetHostName() {
177 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29178}
179
[email protected]a937a06d2009-08-19 21:19:24180class CaptureGroupNameSocketPool : public TCPClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31181 public:
[email protected]a937a06d2009-08-19 21:19:24182 CaptureGroupNameSocketPool() : TCPClientSocketPool(0, 0, NULL, NULL) {}
[email protected]d80a4322009-08-14 07:07:49183 const std::string last_group_name_received() const {
184 return last_group_name_;
185 }
186
[email protected]684970b2009-08-14 04:54:46187 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49188 const void* socket_params,
[email protected]04e5be32009-06-26 20:00:31189 int priority,
190 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46191 CompletionCallback* callback,
192 LoadLog* load_log) {
[email protected]04e5be32009-06-26 20:00:31193 last_group_name_ = group_name;
194 return ERR_IO_PENDING;
195 }
[email protected]04e5be32009-06-26 20:00:31196 virtual void CancelRequest(const std::string& group_name,
197 const ClientSocketHandle* handle) { }
198 virtual void ReleaseSocket(const std::string& group_name,
199 ClientSocket* socket) {}
200 virtual void CloseIdleSockets() {}
201 virtual HostResolver* GetHostResolver() const {
202 return NULL;
203 }
204 virtual int IdleSocketCount() const {
205 return 0;
206 }
207 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
208 return 0;
209 }
210 virtual LoadState GetLoadState(const std::string& group_name,
211 const ClientSocketHandle* handle) const {
212 return LOAD_STATE_IDLE;
213 }
[email protected]d80a4322009-08-14 07:07:49214
215 private:
[email protected]04e5be32009-06-26 20:00:31216 std::string last_group_name_;
217};
218
[email protected]231d5a32008-09-13 00:45:27219//-----------------------------------------------------------------------------
220
221TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59222 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40223 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43224 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27225}
226
227TEST_F(HttpNetworkTransactionTest, SimpleGET) {
228 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35229 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
230 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42231 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27232 };
[email protected]231d5a32008-09-13 00:45:27233 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42234 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27235 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
236 EXPECT_EQ("hello world", out.response_data);
237}
238
239// Response with no status line.
240TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
241 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35242 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42243 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27244 };
[email protected]231d5a32008-09-13 00:45:27245 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42246 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27247 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
248 EXPECT_EQ("hello world", out.response_data);
249}
250
251// Allow up to 4 bytes of junk to precede status line.
252TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
253 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35254 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42255 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27256 };
257 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42258 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27259 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
260 EXPECT_EQ("DATA", out.response_data);
261}
262
263// Allow up to 4 bytes of junk to precede status line.
264TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
265 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35266 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42267 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27268 };
269 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42270 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27271 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
272 EXPECT_EQ("DATA", out.response_data);
273}
274
275// Beyond 4 bytes of slop and it should fail to find a status line.
276TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
277 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35278 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42279 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27280 };
281 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42282 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25283 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
284 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27285}
286
287// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
288TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
289 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35290 MockRead("\n"),
291 MockRead("\n"),
292 MockRead("Q"),
293 MockRead("J"),
294 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42295 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27296 };
297 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42298 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27299 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
300 EXPECT_EQ("DATA", out.response_data);
301}
302
303// Close the connection before enough bytes to have a status line.
304TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
305 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35306 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42307 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27308 };
309 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42310 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27311 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
312 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52313}
314
[email protected]f9d44aa2008-09-23 23:57:17315// Simulate a 204 response, lacking a Content-Length header, sent over a
316// persistent connection. The response should still terminate since a 204
317// cannot have a response body.
318TEST_F(HttpNetworkTransactionTest, StopsReading204) {
319 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35320 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
321 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42322 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17323 };
324 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42325 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17326 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
327 EXPECT_EQ("", out.response_data);
328}
329
[email protected]0877e3d2009-10-17 22:29:57330// A simple request using chunked encoding with some extra data after.
331// (Like might be seen in a pipelined response.)
332TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
333 MockRead data_reads[] = {
334 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
335 MockRead("5\r\nHello\r\n"),
336 MockRead("1\r\n"),
337 MockRead(" \r\n"),
338 MockRead("5\r\nworld\r\n"),
339 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
340 MockRead(false, OK),
341 };
342 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
343 EXPECT_EQ(OK, out.rv);
344 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
345 EXPECT_EQ("Hello world", out.response_data);
346}
347
[email protected]ef0faf2e72009-03-05 23:27:23348// Do a request using the HEAD method. Verify that we don't try to read the
349// message body (since HEAD has none).
350TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59351 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40352 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43353 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23354
[email protected]1c773ea12009-04-28 19:58:42355 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23356 request.method = "HEAD";
357 request.url = GURL("http://www.google.com/");
358 request.load_flags = 0;
359
360 MockWrite data_writes1[] = {
361 MockWrite("HEAD / HTTP/1.1\r\n"
362 "Host: www.google.com\r\n"
363 "Connection: keep-alive\r\n"
364 "Content-Length: 0\r\n\r\n"),
365 };
366 MockRead data_reads1[] = {
367 MockRead("HTTP/1.1 404 Not Found\r\n"),
368 MockRead("Server: Blah\r\n"),
369 MockRead("Content-Length: 1234\r\n\r\n"),
370
371 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42372 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23373 };
374
[email protected]5ecc992a42009-11-11 01:41:59375 StaticSocketDataProvider data1(data_reads1, data_writes1);
376 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23377
378 TestCompletionCallback callback1;
379
[email protected]684970b2009-08-14 04:54:46380 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42381 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23382
383 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42384 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23385
[email protected]1c773ea12009-04-28 19:58:42386 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23387 EXPECT_FALSE(response == NULL);
388
389 // Check that the headers got parsed.
390 EXPECT_TRUE(response->headers != NULL);
391 EXPECT_EQ(1234, response->headers->GetContentLength());
392 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
393
394 std::string server_header;
395 void* iter = NULL;
396 bool has_server_header = response->headers->EnumerateHeader(
397 &iter, "Server", &server_header);
398 EXPECT_TRUE(has_server_header);
399 EXPECT_EQ("Blah", server_header);
400
401 // Reading should give EOF right away, since there is no message body
402 // (despite non-zero content-length).
403 std::string response_data;
404 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42405 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23406 EXPECT_EQ("", response_data);
407}
408
initial.commit586acc5fe2008-07-26 22:42:52409TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59410 SessionDependencies session_deps;
411 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52412
413 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35414 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
415 MockRead("hello"),
416 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
417 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42418 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52419 };
[email protected]5ecc992a42009-11-11 01:41:59420 StaticSocketDataProvider data(data_reads, NULL);
421 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52422
423 const char* kExpectedResponseData[] = {
424 "hello", "world"
425 };
426
427 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43428 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52429
[email protected]1c773ea12009-04-28 19:58:42430 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52431 request.method = "GET";
432 request.url = GURL("http://www.google.com/");
433 request.load_flags = 0;
434
435 TestCompletionCallback callback;
436
[email protected]684970b2009-08-14 04:54:46437 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42438 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52439
440 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42441 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52442
[email protected]1c773ea12009-04-28 19:58:42443 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52444 EXPECT_TRUE(response != NULL);
445
446 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25447 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52448
449 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57450 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42451 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25452 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52453 }
454}
455
456TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59457 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40458 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43459 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52460
[email protected]1c773ea12009-04-28 19:58:42461 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52462 request.method = "POST";
463 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42464 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52465 request.upload_data->AppendBytes("foo", 3);
466 request.load_flags = 0;
467
468 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35469 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
470 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
471 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42472 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52473 };
[email protected]5ecc992a42009-11-11 01:41:59474 StaticSocketDataProvider data(data_reads, NULL);
475 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52476
477 TestCompletionCallback callback;
478
[email protected]684970b2009-08-14 04:54:46479 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42480 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52481
482 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42483 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52484
[email protected]1c773ea12009-04-28 19:58:42485 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52486 EXPECT_TRUE(response != NULL);
487
488 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25489 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52490
491 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57492 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42493 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25494 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52495}
496
[email protected]3a2d3662009-03-27 03:49:14497// This test is almost the same as Ignores100 above, but the response contains
498// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57499// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14500TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59501 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40502 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43503 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14504
[email protected]1c773ea12009-04-28 19:58:42505 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14506 request.method = "GET";
507 request.url = GURL("http://www.foo.com/");
508 request.load_flags = 0;
509
510 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57511 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
512 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14513 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42514 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14515 };
[email protected]5ecc992a42009-11-11 01:41:59516 StaticSocketDataProvider data(data_reads, NULL);
517 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14518
519 TestCompletionCallback callback;
520
[email protected]684970b2009-08-14 04:54:46521 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42522 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14523
524 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42525 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14526
[email protected]1c773ea12009-04-28 19:58:42527 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14528 EXPECT_TRUE(response != NULL);
529
530 EXPECT_TRUE(response->headers != NULL);
531 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
532
533 std::string response_data;
534 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42535 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14536 EXPECT_EQ("hello world", response_data);
537}
538
[email protected]3d2a59b2008-09-26 19:44:25539// read_failure specifies a read failure that should cause the network
540// transaction to resend the request.
541void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
542 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59543 SessionDependencies session_deps;
544 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52545
[email protected]1c773ea12009-04-28 19:58:42546 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52547 request.method = "GET";
548 request.url = GURL("http://www.foo.com/");
549 request.load_flags = 0;
550
551 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35552 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
553 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25554 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52555 };
[email protected]5ecc992a42009-11-11 01:41:59556 StaticSocketDataProvider data1(data1_reads, NULL);
557 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52558
559 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35560 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
561 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42562 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52563 };
[email protected]5ecc992a42009-11-11 01:41:59564 StaticSocketDataProvider data2(data2_reads, NULL);
565 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52566
567 const char* kExpectedResponseData[] = {
568 "hello", "world"
569 };
570
571 for (int i = 0; i < 2; ++i) {
572 TestCompletionCallback callback;
573
[email protected]5695b8c2009-09-30 21:36:43574 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52575
[email protected]684970b2009-08-14 04:54:46576 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42577 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52578
579 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42580 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52581
[email protected]1c773ea12009-04-28 19:58:42582 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52583 EXPECT_TRUE(response != NULL);
584
585 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25586 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52587
588 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57589 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42590 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25591 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52592 }
593}
[email protected]3d2a59b2008-09-26 19:44:25594
595TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42596 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25597 KeepAliveConnectionResendRequestTest(read_failure);
598}
599
600TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42601 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25602 KeepAliveConnectionResendRequestTest(read_failure);
603}
604
605TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59606 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40607 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43608 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25609
[email protected]1c773ea12009-04-28 19:58:42610 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25611 request.method = "GET";
612 request.url = GURL("http://www.google.com/");
613 request.load_flags = 0;
614
615 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42616 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35617 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
618 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42619 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25620 };
[email protected]5ecc992a42009-11-11 01:41:59621 StaticSocketDataProvider data(data_reads, NULL);
622 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25623
624 TestCompletionCallback callback;
625
[email protected]684970b2009-08-14 04:54:46626 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42627 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25628
629 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42630 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25631
[email protected]1c773ea12009-04-28 19:58:42632 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25633 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25634}
635
636// What do various browsers do when the server closes a non-keepalive
637// connection without sending any response header or body?
638//
639// IE7: error page
640// Safari 3.1.2 (Windows): error page
641// Firefox 3.0.1: blank page
642// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42643// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
644// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25645TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
646 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42647 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35648 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
649 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42650 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25651 };
652 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42653 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25654}
[email protected]038e9a32008-10-08 22:40:16655
656// Test the request-challenge-retry sequence for basic auth.
657// (basic auth is the easiest to mock, because it has no randomness).
658TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59659 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40660 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43661 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16662
[email protected]1c773ea12009-04-28 19:58:42663 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16664 request.method = "GET";
665 request.url = GURL("http://www.google.com/");
666 request.load_flags = 0;
667
[email protected]f9ee6b52008-11-08 06:46:23668 MockWrite data_writes1[] = {
669 MockWrite("GET / HTTP/1.1\r\n"
670 "Host: www.google.com\r\n"
671 "Connection: keep-alive\r\n\r\n"),
672 };
673
[email protected]038e9a32008-10-08 22:40:16674 MockRead data_reads1[] = {
675 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
676 // Give a couple authenticate options (only the middle one is actually
677 // supported).
[email protected]22927ad2009-09-21 19:56:19678 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16679 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
680 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
681 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
682 // Large content-length -- won't matter, as connection will be reset.
683 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42684 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16685 };
686
687 // After calling trans->RestartWithAuth(), this is the request we should
688 // be issuing -- the final header line contains the credentials.
689 MockWrite data_writes2[] = {
690 MockWrite("GET / HTTP/1.1\r\n"
691 "Host: www.google.com\r\n"
692 "Connection: keep-alive\r\n"
693 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
694 };
695
696 // Lastly, the server responds with the actual content.
697 MockRead data_reads2[] = {
698 MockRead("HTTP/1.0 200 OK\r\n"),
699 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
700 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42701 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16702 };
703
[email protected]5ecc992a42009-11-11 01:41:59704 StaticSocketDataProvider data1(data_reads1, data_writes1);
705 StaticSocketDataProvider data2(data_reads2, data_writes2);
706 session_deps.socket_factory.AddSocketDataProvider(&data1);
707 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16708
709 TestCompletionCallback callback1;
710
[email protected]684970b2009-08-14 04:54:46711 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42712 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16713
714 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42715 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16716
[email protected]1c773ea12009-04-28 19:58:42717 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16718 EXPECT_FALSE(response == NULL);
719
720 // The password prompt info should have been set in response->auth_challenge.
721 EXPECT_FALSE(response->auth_challenge.get() == NULL);
722
[email protected]71e4573a2009-05-21 22:03:00723 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16724 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
725 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
726
727 TestCompletionCallback callback2;
728
729 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42730 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16731
732 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42733 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16734
735 response = trans->GetResponseInfo();
736 EXPECT_FALSE(response == NULL);
737 EXPECT_TRUE(response->auth_challenge.get() == NULL);
738 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16739}
740
[email protected]861fcd52009-08-26 02:33:46741TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
742 SessionDependencies session_deps;
743 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43744 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46745
746 HttpRequestInfo request;
747 request.method = "GET";
748 request.url = GURL("http://www.google.com/");
749 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
750
751 MockWrite data_writes[] = {
752 MockWrite("GET / HTTP/1.1\r\n"
753 "Host: www.google.com\r\n"
754 "Connection: keep-alive\r\n\r\n"),
755 };
756
757 MockRead data_reads[] = {
758 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
759 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
760 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
761 // Large content-length -- won't matter, as connection will be reset.
762 MockRead("Content-Length: 10000\r\n\r\n"),
763 MockRead(false, ERR_FAILED),
764 };
765
[email protected]5ecc992a42009-11-11 01:41:59766 StaticSocketDataProvider data(data_reads, data_writes);
767 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46768 TestCompletionCallback callback;
769
770 int rv = trans->Start(&request, &callback, NULL);
771 EXPECT_EQ(ERR_IO_PENDING, rv);
772
773 rv = callback.WaitForResult();
774 EXPECT_EQ(0, rv);
775
776 const HttpResponseInfo* response = trans->GetResponseInfo();
777 ASSERT_FALSE(response == NULL);
778 EXPECT_TRUE(response->auth_challenge.get() == NULL);
779}
780
[email protected]2d2697f92009-02-18 21:00:32781// Test the request-challenge-retry sequence for basic auth, over a keep-alive
782// connection.
783TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59784 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40785 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43786 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32787
[email protected]1c773ea12009-04-28 19:58:42788 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32789 request.method = "GET";
790 request.url = GURL("http://www.google.com/");
791 request.load_flags = 0;
792
793 MockWrite data_writes1[] = {
794 MockWrite("GET / HTTP/1.1\r\n"
795 "Host: www.google.com\r\n"
796 "Connection: keep-alive\r\n\r\n"),
797
798 // After calling trans->RestartWithAuth(), this is the request we should
799 // be issuing -- the final header line contains the credentials.
800 MockWrite("GET / HTTP/1.1\r\n"
801 "Host: www.google.com\r\n"
802 "Connection: keep-alive\r\n"
803 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
804 };
805
806 MockRead data_reads1[] = {
807 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
808 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
809 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
810 MockRead("Content-Length: 14\r\n\r\n"),
811 MockRead("Unauthorized\r\n"),
812
813 // Lastly, the server responds with the actual content.
814 MockRead("HTTP/1.1 200 OK\r\n"),
815 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
816 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42817 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32818 };
819
[email protected]5ecc992a42009-11-11 01:41:59820 StaticSocketDataProvider data1(data_reads1, data_writes1);
821 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32822
823 TestCompletionCallback callback1;
824
[email protected]684970b2009-08-14 04:54:46825 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42826 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32827
828 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42829 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32830
[email protected]1c773ea12009-04-28 19:58:42831 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32832 EXPECT_FALSE(response == NULL);
833
834 // The password prompt info should have been set in response->auth_challenge.
835 EXPECT_FALSE(response->auth_challenge.get() == NULL);
836
[email protected]71e4573a2009-05-21 22:03:00837 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32838 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
839 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
840
841 TestCompletionCallback callback2;
842
843 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42844 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32845
846 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42847 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32848
849 response = trans->GetResponseInfo();
850 EXPECT_FALSE(response == NULL);
851 EXPECT_TRUE(response->auth_challenge.get() == NULL);
852 EXPECT_EQ(100, response->headers->GetContentLength());
853}
854
855// Test the request-challenge-retry sequence for basic auth, over a keep-alive
856// connection and with no response body to drain.
857TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59858 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40859 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43860 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32861
[email protected]1c773ea12009-04-28 19:58:42862 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32863 request.method = "GET";
864 request.url = GURL("http://www.google.com/");
865 request.load_flags = 0;
866
867 MockWrite data_writes1[] = {
868 MockWrite("GET / HTTP/1.1\r\n"
869 "Host: www.google.com\r\n"
870 "Connection: keep-alive\r\n\r\n"),
871
872 // After calling trans->RestartWithAuth(), this is the request we should
873 // be issuing -- the final header line contains the credentials.
874 MockWrite("GET / HTTP/1.1\r\n"
875 "Host: www.google.com\r\n"
876 "Connection: keep-alive\r\n"
877 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
878 };
879
[email protected]2d2697f92009-02-18 21:00:32880 MockRead data_reads1[] = {
881 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
882 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:31883 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:32884
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]5ecc992a42009-11-11 01:41:59892 StaticSocketDataProvider data1(data_reads1, data_writes1);
893 session_deps.socket_factory.AddSocketDataProvider(&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]5ecc992a42009-11-11 01:41:59972 StaticSocketDataProvider data1(data_reads1, data_writes1);
973 session_deps.socket_factory.AddSocketDataProvider(&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
[email protected]11203f012009-11-12 23:02:311008// connection, but the server gets impatient and closes the connection.
1009TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1010 SessionDependencies session_deps;
1011 scoped_ptr<HttpTransaction> trans(
1012 new HttpNetworkTransaction(CreateSession(&session_deps)));
1013
1014 HttpRequestInfo request;
1015 request.method = "GET";
1016 request.url = GURL("http://www.google.com/");
1017 request.load_flags = 0;
1018
1019 MockWrite data_writes1[] = {
1020 MockWrite("GET / HTTP/1.1\r\n"
1021 "Host: www.google.com\r\n"
1022 "Connection: keep-alive\r\n\r\n"),
1023 // This simulates the seemingly successful write to a closed connection
1024 // if the bug is not fixed.
1025 MockWrite("GET / HTTP/1.1\r\n"
1026 "Host: www.google.com\r\n"
1027 "Connection: keep-alive\r\n"
1028 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1029 };
1030
1031 MockRead data_reads1[] = {
1032 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1033 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1034 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1035 MockRead("Content-Length: 14\r\n\r\n"),
1036 // Tell MockTCPClientSocket to simulate the server closing the connection.
1037 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1038 MockRead("Unauthorized\r\n"),
1039 MockRead(false, OK), // The server closes the connection.
1040 };
1041
1042 // After calling trans->RestartWithAuth(), this is the request we should
1043 // be issuing -- the final header line contains the credentials.
1044 MockWrite data_writes2[] = {
1045 MockWrite("GET / HTTP/1.1\r\n"
1046 "Host: www.google.com\r\n"
1047 "Connection: keep-alive\r\n"
1048 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1049 };
1050
1051 // Lastly, the server responds with the actual content.
1052 MockRead data_reads2[] = {
1053 MockRead("HTTP/1.1 200 OK\r\n"),
1054 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1055 MockRead("Content-Length: 100\r\n\r\n"),
1056 MockRead(false, OK),
1057 };
1058
1059 StaticSocketDataProvider data1(data_reads1, data_writes1);
1060 StaticSocketDataProvider data2(data_reads2, data_writes2);
1061 session_deps.socket_factory.AddSocketDataProvider(&data1);
1062 session_deps.socket_factory.AddSocketDataProvider(&data2);
1063
1064 TestCompletionCallback callback1;
1065
1066 int rv = trans->Start(&request, &callback1, NULL);
1067 EXPECT_EQ(ERR_IO_PENDING, rv);
1068
1069 rv = callback1.WaitForResult();
1070 EXPECT_EQ(OK, rv);
1071
1072 const HttpResponseInfo* response = trans->GetResponseInfo();
1073 EXPECT_FALSE(response == NULL);
1074
1075 // The password prompt info should have been set in response->auth_challenge.
1076 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1077
1078 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1079 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1080 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1081
1082 TestCompletionCallback callback2;
1083
1084 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1085 EXPECT_EQ(ERR_IO_PENDING, rv);
1086
1087 rv = callback2.WaitForResult();
1088 EXPECT_EQ(OK, rv);
1089
1090 response = trans->GetResponseInfo();
1091 ASSERT_FALSE(response == NULL);
1092 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1093 EXPECT_EQ(100, response->headers->GetContentLength());
1094}
1095
1096// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321097// proxy connection, when setting up an SSL tunnel.
1098TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1099 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591100 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1101 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321102
[email protected]5695b8c2009-09-30 21:36:431103 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321104
[email protected]1c773ea12009-04-28 19:58:421105 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321106 request.method = "GET";
1107 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461108 // Ensure that proxy authentication is attempted even
1109 // when the no authentication data flag is set.
1110 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321111
1112 // Since we have proxy, should try to establish tunnel.
1113 MockWrite data_writes1[] = {
1114 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451115 "Host: www.google.com\r\n"
1116 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321117
1118 // After calling trans->RestartWithAuth(), this is the request we should
1119 // be issuing -- the final header line contains the credentials.
1120 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1121 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451122 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321123 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1124 };
1125
1126 // The proxy responds to the connect with a 407, using a persistent
1127 // connection.
1128 MockRead data_reads1[] = {
1129 // No credentials.
1130 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1131 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1132 MockRead("Content-Length: 10\r\n\r\n"),
1133 MockRead("0123456789"),
1134
1135 // Wrong credentials (wrong password).
1136 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1137 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1138 MockRead("Content-Length: 10\r\n\r\n"),
1139 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421140 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321141 };
1142
[email protected]5ecc992a42009-11-11 01:41:591143 StaticSocketDataProvider data1(data_reads1, data_writes1);
1144 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321145
1146 TestCompletionCallback callback1;
1147
[email protected]684970b2009-08-14 04:54:461148 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421149 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321150
1151 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421152 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321153
[email protected]1c773ea12009-04-28 19:58:421154 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321155 EXPECT_FALSE(response == NULL);
1156
1157 EXPECT_TRUE(response->headers->IsKeepAlive());
1158 EXPECT_EQ(407, response->headers->response_code());
1159 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421160 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321161
1162 // The password prompt info should have been set in response->auth_challenge.
1163 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1164
[email protected]71e4573a2009-05-21 22:03:001165 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321166 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1167 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1168
1169 TestCompletionCallback callback2;
1170
1171 // Wrong password (should be "bar").
1172 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421173 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321174
1175 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421176 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321177
1178 response = trans->GetResponseInfo();
1179 EXPECT_FALSE(response == NULL);
1180
1181 EXPECT_TRUE(response->headers->IsKeepAlive());
1182 EXPECT_EQ(407, response->headers->response_code());
1183 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421184 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321185
1186 // The password prompt info should have been set in response->auth_challenge.
1187 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1188
[email protected]71e4573a2009-05-21 22:03:001189 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321190 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1191 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1192}
1193
[email protected]a8e9b162009-03-12 00:06:441194// Test that we don't read the response body when we fail to establish a tunnel,
1195// even if the user cancels the proxy's auth attempt.
1196TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1197 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591198 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441199
[email protected]e44de5d2009-06-05 20:12:451200 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441201
[email protected]5695b8c2009-09-30 21:36:431202 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441203
[email protected]1c773ea12009-04-28 19:58:421204 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441205 request.method = "GET";
1206 request.url = GURL("https://www.google.com/");
1207 request.load_flags = 0;
1208
1209 // Since we have proxy, should try to establish tunnel.
1210 MockWrite data_writes[] = {
1211 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451212 "Host: www.google.com\r\n"
1213 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441214 };
1215
1216 // The proxy responds to the connect with a 407.
1217 MockRead data_reads[] = {
1218 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1219 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1220 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421221 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441222 };
1223
[email protected]5ecc992a42009-11-11 01:41:591224 StaticSocketDataProvider data(data_reads, data_writes);
1225 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441226
1227 TestCompletionCallback callback;
1228
[email protected]684970b2009-08-14 04:54:461229 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421230 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441231
1232 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421233 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441234
[email protected]1c773ea12009-04-28 19:58:421235 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441236 EXPECT_FALSE(response == NULL);
1237
1238 EXPECT_TRUE(response->headers->IsKeepAlive());
1239 EXPECT_EQ(407, response->headers->response_code());
1240 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421241 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441242
1243 std::string response_data;
1244 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421245 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441246}
1247
[email protected]ff007e162009-05-23 09:13:151248void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081249 const MockRead& status, int expected_status) {
1250 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591251 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081252
[email protected]228ff742009-06-05 01:19:591253 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081254
[email protected]5695b8c2009-09-30 21:36:431255 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081256
[email protected]1c773ea12009-04-28 19:58:421257 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081258 request.method = "GET";
1259 request.url = GURL("https://www.google.com/");
1260 request.load_flags = 0;
1261
1262 // Since we have proxy, should try to establish tunnel.
1263 MockWrite data_writes[] = {
1264 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451265 "Host: www.google.com\r\n"
1266 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081267 };
1268
1269 MockRead data_reads[] = {
1270 status,
1271 MockRead("Content-Length: 10\r\n\r\n"),
1272 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421273 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081274 };
1275
[email protected]5ecc992a42009-11-11 01:41:591276 StaticSocketDataProvider data(data_reads, data_writes);
1277 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081278
1279 TestCompletionCallback callback;
1280
[email protected]684970b2009-08-14 04:54:461281 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421282 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081283
1284 rv = callback.WaitForResult();
1285 EXPECT_EQ(expected_status, rv);
1286}
1287
[email protected]ff007e162009-05-23 09:13:151288void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081289 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421290 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081291}
1292
1293TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1294 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1295}
1296
1297TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1298 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1299}
1300
1301TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1302 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1303}
1304
1305TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1306 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1307}
1308
1309TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1310 ConnectStatusHelper(
1311 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1312}
1313
1314TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1315 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1316}
1317
1318TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1319 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1320}
1321
1322TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1323 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1324}
1325
1326TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1327 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1328}
1329
1330TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1331 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1332}
1333
1334TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1335 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1336}
1337
1338TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1339 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1340}
1341
1342TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1343 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1344}
1345
1346TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1347 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1348}
1349
1350TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1351 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1352}
1353
1354TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1355 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1356}
1357
1358TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1359 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1360}
1361
1362TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1363 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1364}
1365
1366TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1367 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1368}
1369
1370TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1371 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1372}
1373
1374TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1375 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1376}
1377
1378TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1379 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1380}
1381
1382TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1383 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1384}
1385
1386TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1387 ConnectStatusHelperWithExpectedStatus(
1388 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421389 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081390}
1391
1392TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1393 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1394}
1395
1396TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1397 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1398}
1399
1400TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1401 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1402}
1403
1404TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1405 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1406}
1407
1408TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1409 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1410}
1411
1412TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1413 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1414}
1415
1416TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1417 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1418}
1419
1420TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1421 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1422}
1423
1424TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1425 ConnectStatusHelper(
1426 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1427}
1428
1429TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1430 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1431}
1432
1433TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1434 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1435}
1436
1437TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1438 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1439}
1440
1441TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1442 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1443}
1444
1445TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1446 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1447}
1448
1449TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1450 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1451}
1452
1453TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1454 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1455}
1456
[email protected]038e9a32008-10-08 22:40:161457// Test the flow when both the proxy server AND origin server require
1458// authentication. Again, this uses basic auth for both since that is
1459// the simplest to mock.
1460TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591461 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011462
[email protected]038e9a32008-10-08 22:40:161463 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421464 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431465 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161466
[email protected]1c773ea12009-04-28 19:58:421467 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161468 request.method = "GET";
1469 request.url = GURL("http://www.google.com/");
1470 request.load_flags = 0;
1471
[email protected]f9ee6b52008-11-08 06:46:231472 MockWrite data_writes1[] = {
1473 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1474 "Host: www.google.com\r\n"
1475 "Proxy-Connection: keep-alive\r\n\r\n"),
1476 };
1477
[email protected]038e9a32008-10-08 22:40:161478 MockRead data_reads1[] = {
1479 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1480 // Give a couple authenticate options (only the middle one is actually
1481 // supported).
[email protected]22927ad2009-09-21 19:56:191482 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161483 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1484 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1485 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1486 // Large content-length -- won't matter, as connection will be reset.
1487 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421488 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161489 };
1490
1491 // After calling trans->RestartWithAuth() the first time, this is the
1492 // request we should be issuing -- the final header line contains the
1493 // proxy's credentials.
1494 MockWrite data_writes2[] = {
1495 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1496 "Host: www.google.com\r\n"
1497 "Proxy-Connection: keep-alive\r\n"
1498 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1499 };
1500
1501 // Now the proxy server lets the request pass through to origin server.
1502 // The origin server responds with a 401.
1503 MockRead data_reads2[] = {
1504 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1505 // Note: We are using the same realm-name as the proxy server. This is
1506 // completely valid, as realms are unique across hosts.
1507 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1508 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1509 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421510 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161511 };
1512
1513 // After calling trans->RestartWithAuth() the second time, we should send
1514 // the credentials for both the proxy and origin server.
1515 MockWrite data_writes3[] = {
1516 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1517 "Host: www.google.com\r\n"
1518 "Proxy-Connection: keep-alive\r\n"
1519 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1520 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1521 };
1522
1523 // Lastly we get the desired content.
1524 MockRead data_reads3[] = {
1525 MockRead("HTTP/1.0 200 OK\r\n"),
1526 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1527 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421528 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161529 };
1530
[email protected]5ecc992a42009-11-11 01:41:591531 StaticSocketDataProvider data1(data_reads1, data_writes1);
1532 StaticSocketDataProvider data2(data_reads2, data_writes2);
1533 StaticSocketDataProvider data3(data_reads3, data_writes3);
1534 session_deps.socket_factory.AddSocketDataProvider(&data1);
1535 session_deps.socket_factory.AddSocketDataProvider(&data2);
1536 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161537
1538 TestCompletionCallback callback1;
1539
[email protected]684970b2009-08-14 04:54:461540 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421541 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161542
1543 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421544 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161545
[email protected]1c773ea12009-04-28 19:58:421546 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161547 EXPECT_FALSE(response == NULL);
1548
1549 // The password prompt info should have been set in response->auth_challenge.
1550 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1551
[email protected]71e4573a2009-05-21 22:03:001552 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161553 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1554 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1555
1556 TestCompletionCallback callback2;
1557
1558 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421559 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161560
1561 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421562 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161563
1564 response = trans->GetResponseInfo();
1565 EXPECT_FALSE(response == NULL);
1566 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1567
[email protected]71e4573a2009-05-21 22:03:001568 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161569 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1570 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1571
1572 TestCompletionCallback callback3;
1573
1574 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421575 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161576
1577 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421578 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161579
1580 response = trans->GetResponseInfo();
1581 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1582 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161583}
[email protected]4ddaf2502008-10-23 18:26:191584
[email protected]ea9dc9a2009-09-05 00:43:321585// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1586// can't hook into its internals to cause it to generate predictable NTLM
1587// authorization headers.
1588#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291589// The NTLM authentication unit tests were generated by capturing the HTTP
1590// requests and responses using Fiddler 2 and inspecting the generated random
1591// bytes in the debugger.
1592
1593// Enter the correct password and authenticate successfully.
1594TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421595 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201596 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591597 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401598 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431599 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241600
[email protected]1c773ea12009-04-28 19:58:421601 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241602 request.method = "GET";
1603 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1604 request.load_flags = 0;
1605
1606 MockWrite data_writes1[] = {
1607 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1608 "Host: 172.22.68.17\r\n"
1609 "Connection: keep-alive\r\n\r\n"),
1610 };
1611
1612 MockRead data_reads1[] = {
1613 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1614 // Negotiate and NTLM are often requested together. We only support NTLM.
1615 MockRead("WWW-Authenticate: Negotiate\r\n"),
1616 MockRead("WWW-Authenticate: NTLM\r\n"),
1617 MockRead("Connection: close\r\n"),
1618 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361619 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241620 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421621 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241622 };
1623
1624 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221625 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241626 // request we should be issuing -- the final header line contains a Type
1627 // 1 message.
1628 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1629 "Host: 172.22.68.17\r\n"
1630 "Connection: keep-alive\r\n"
1631 "Authorization: NTLM "
1632 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1633
1634 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1635 // (the credentials for the origin server). The second request continues
1636 // on the same connection.
1637 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1638 "Host: 172.22.68.17\r\n"
1639 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291640 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1641 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1642 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1643 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1644 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241645 };
1646
1647 MockRead data_reads2[] = {
1648 // The origin server responds with a Type 2 message.
1649 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1650 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291651 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241652 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1653 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1654 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1655 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1656 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1657 "BtAAAAAAA=\r\n"),
1658 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361659 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241660 MockRead("You are not authorized to view this page\r\n"),
1661
1662 // Lastly we get the desired content.
1663 MockRead("HTTP/1.1 200 OK\r\n"),
1664 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1665 MockRead("Content-Length: 13\r\n\r\n"),
1666 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421667 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241668 };
1669
[email protected]5ecc992a42009-11-11 01:41:591670 StaticSocketDataProvider data1(data_reads1, data_writes1);
1671 StaticSocketDataProvider data2(data_reads2, data_writes2);
1672 session_deps.socket_factory.AddSocketDataProvider(&data1);
1673 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241674
1675 TestCompletionCallback callback1;
1676
[email protected]684970b2009-08-14 04:54:461677 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421678 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241679
1680 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421681 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241682
[email protected]0757e7702009-03-27 04:00:221683 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1684 TestCompletionCallback callback2;
1685 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421686 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221687 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421688 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221689 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1690
[email protected]1c773ea12009-04-28 19:58:421691 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241692 EXPECT_FALSE(response == NULL);
1693
1694 // The password prompt info should have been set in response->auth_challenge.
1695 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1696
[email protected]71e4573a2009-05-21 22:03:001697 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241698 EXPECT_EQ(L"", response->auth_challenge->realm);
1699 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1700
[email protected]0757e7702009-03-27 04:00:221701 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241702
[email protected]0757e7702009-03-27 04:00:221703 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421704 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241705
[email protected]0757e7702009-03-27 04:00:221706 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421707 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241708
1709 response = trans->GetResponseInfo();
1710 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1711 EXPECT_EQ(13, response->headers->GetContentLength());
1712}
1713
[email protected]385a4672009-03-11 22:21:291714// Enter a wrong password, and then the correct one.
1715TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421716 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201717 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591718 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401719 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431720 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291721
[email protected]1c773ea12009-04-28 19:58:421722 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291723 request.method = "GET";
1724 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1725 request.load_flags = 0;
1726
1727 MockWrite data_writes1[] = {
1728 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1729 "Host: 172.22.68.17\r\n"
1730 "Connection: keep-alive\r\n\r\n"),
1731 };
1732
1733 MockRead data_reads1[] = {
1734 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1735 // Negotiate and NTLM are often requested together. We only support NTLM.
1736 MockRead("WWW-Authenticate: Negotiate\r\n"),
1737 MockRead("WWW-Authenticate: NTLM\r\n"),
1738 MockRead("Connection: close\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 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421742 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291743 };
1744
1745 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221746 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291747 // request we should be issuing -- the final header line contains a Type
1748 // 1 message.
1749 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1750 "Host: 172.22.68.17\r\n"
1751 "Connection: keep-alive\r\n"
1752 "Authorization: NTLM "
1753 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1754
1755 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1756 // (the credentials for the origin server). The second request continues
1757 // on the same connection.
1758 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1759 "Host: 172.22.68.17\r\n"
1760 "Connection: keep-alive\r\n"
1761 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1762 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1763 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1764 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1765 "4Ww7b7E=\r\n\r\n"),
1766 };
1767
1768 MockRead data_reads2[] = {
1769 // The origin server responds with a Type 2 message.
1770 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1771 MockRead("WWW-Authenticate: NTLM "
1772 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1773 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1774 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1775 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1776 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1777 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1778 "BtAAAAAAA=\r\n"),
1779 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361780 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291781 MockRead("You are not authorized to view this page\r\n"),
1782
1783 // Wrong password.
1784 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1785 MockRead("WWW-Authenticate: Negotiate\r\n"),
1786 MockRead("WWW-Authenticate: NTLM\r\n"),
1787 MockRead("Connection: close\r\n"),
1788 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361789 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291790 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421791 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291792 };
1793
1794 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221795 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291796 // request we should be issuing -- the final header line contains a Type
1797 // 1 message.
1798 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1799 "Host: 172.22.68.17\r\n"
1800 "Connection: keep-alive\r\n"
1801 "Authorization: NTLM "
1802 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1803
1804 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1805 // (the credentials for the origin server). The second request continues
1806 // on the same connection.
1807 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1808 "Host: 172.22.68.17\r\n"
1809 "Connection: keep-alive\r\n"
1810 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1811 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1812 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1813 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1814 "+4MUm7c=\r\n\r\n"),
1815 };
1816
1817 MockRead data_reads3[] = {
1818 // The origin server responds with a Type 2 message.
1819 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1820 MockRead("WWW-Authenticate: NTLM "
1821 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1822 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1823 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1824 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1825 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1826 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1827 "BtAAAAAAA=\r\n"),
1828 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361829 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291830 MockRead("You are not authorized to view this page\r\n"),
1831
1832 // Lastly we get the desired content.
1833 MockRead("HTTP/1.1 200 OK\r\n"),
1834 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1835 MockRead("Content-Length: 13\r\n\r\n"),
1836 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421837 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291838 };
1839
[email protected]5ecc992a42009-11-11 01:41:591840 StaticSocketDataProvider data1(data_reads1, data_writes1);
1841 StaticSocketDataProvider data2(data_reads2, data_writes2);
1842 StaticSocketDataProvider data3(data_reads3, data_writes3);
1843 session_deps.socket_factory.AddSocketDataProvider(&data1);
1844 session_deps.socket_factory.AddSocketDataProvider(&data2);
1845 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:291846
1847 TestCompletionCallback callback1;
1848
[email protected]684970b2009-08-14 04:54:461849 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421850 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291851
1852 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421853 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291854
[email protected]0757e7702009-03-27 04:00:221855 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291856 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221857 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421858 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291859 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421860 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221861 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291862
[email protected]1c773ea12009-04-28 19:58:421863 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291864 EXPECT_FALSE(response == NULL);
1865
1866 // The password prompt info should have been set in response->auth_challenge.
1867 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1868
[email protected]71e4573a2009-05-21 22:03:001869 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291870 EXPECT_EQ(L"", response->auth_challenge->realm);
1871 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1872
1873 TestCompletionCallback callback3;
1874
[email protected]0757e7702009-03-27 04:00:221875 // Enter the wrong password.
1876 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421877 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291878
1879 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421880 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291881
[email protected]0757e7702009-03-27 04:00:221882 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1883 TestCompletionCallback callback4;
1884 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421885 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221886 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421887 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221888 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1889
1890 response = trans->GetResponseInfo();
1891 EXPECT_FALSE(response == NULL);
1892
1893 // The password prompt info should have been set in response->auth_challenge.
1894 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1895
[email protected]71e4573a2009-05-21 22:03:001896 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221897 EXPECT_EQ(L"", response->auth_challenge->realm);
1898 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1899
1900 TestCompletionCallback callback5;
1901
1902 // Now enter the right password.
1903 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:421904 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221905
1906 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421907 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221908
[email protected]385a4672009-03-11 22:21:291909 response = trans->GetResponseInfo();
1910 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1911 EXPECT_EQ(13, response->headers->GetContentLength());
1912}
[email protected]ea9dc9a2009-09-05 00:43:321913#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:291914
[email protected]4ddaf2502008-10-23 18:26:191915// Test reading a server response which has only headers, and no body.
1916// After some maximum number of bytes is consumed, the transaction should
1917// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
1918TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:591919 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401920 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431921 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:191922
[email protected]1c773ea12009-04-28 19:58:421923 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:191924 request.method = "GET";
1925 request.url = GURL("http://www.google.com/");
1926 request.load_flags = 0;
1927
[email protected]b75b7b2f2009-10-06 00:54:531928 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:431929 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:531930 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:191931
1932 MockRead data_reads[] = {
1933 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:431934 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:191935 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:421936 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:191937 };
[email protected]5ecc992a42009-11-11 01:41:591938 StaticSocketDataProvider data(data_reads, NULL);
1939 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:191940
1941 TestCompletionCallback callback;
1942
[email protected]684970b2009-08-14 04:54:461943 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421944 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:191945
1946 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421947 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:191948
[email protected]1c773ea12009-04-28 19:58:421949 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:191950 EXPECT_TRUE(response == NULL);
1951}
[email protected]f4e426b2008-11-05 00:24:491952
1953// Make sure that we don't try to reuse a TCPClientSocket when failing to
1954// establish tunnel.
1955// http://code.google.com/p/chromium/issues/detail?id=3772
1956TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
1957 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591958 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011959
[email protected]228ff742009-06-05 01:19:591960 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:491961
[email protected]5695b8c2009-09-30 21:36:431962 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:491963
[email protected]1c773ea12009-04-28 19:58:421964 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:491965 request.method = "GET";
1966 request.url = GURL("https://www.google.com/");
1967 request.load_flags = 0;
1968
1969 // Since we have proxy, should try to establish tunnel.
1970 MockWrite data_writes1[] = {
1971 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451972 "Host: www.google.com\r\n"
1973 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:491974 };
1975
[email protected]77848d12008-11-14 00:00:221976 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:491977 // connection. Usually a proxy would return 501 (not implemented),
1978 // or 200 (tunnel established).
1979 MockRead data_reads1[] = {
1980 MockRead("HTTP/1.1 404 Not Found\r\n"),
1981 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421982 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:491983 };
1984
[email protected]5ecc992a42009-11-11 01:41:591985 StaticSocketDataProvider data1(data_reads1, data_writes1);
1986 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:491987
1988 TestCompletionCallback callback1;
1989
[email protected]684970b2009-08-14 04:54:461990 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421991 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:491992
1993 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421994 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:491995
[email protected]1c773ea12009-04-28 19:58:421996 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:081997 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:491998
[email protected]b4404c02009-04-10 16:38:521999 // Empty the current queue. This is necessary because idle sockets are
2000 // added to the connection pool asynchronously with a PostTask.
2001 MessageLoop::current()->RunAllPending();
2002
[email protected]f4e426b2008-11-05 00:24:492003 // We now check to make sure the TCPClientSocket was not added back to
2004 // the pool.
[email protected]a937a06d2009-08-19 21:19:242005 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492006 trans.reset();
[email protected]b4404c02009-04-10 16:38:522007 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492008 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242009 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492010}
[email protected]372d34a2008-11-05 21:30:512011
[email protected]1b157c02009-04-21 01:55:402012// Make sure that we recycle a socket after reading all of the response body.
2013TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592014 SessionDependencies session_deps;
2015 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402016
[email protected]5695b8c2009-09-30 21:36:432017 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402018
[email protected]1c773ea12009-04-28 19:58:422019 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402020 request.method = "GET";
2021 request.url = GURL("http://www.google.com/");
2022 request.load_flags = 0;
2023
2024 MockRead data_reads[] = {
2025 // A part of the response body is received with the response headers.
2026 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2027 // The rest of the response body is received in two parts.
2028 MockRead("lo"),
2029 MockRead(" world"),
2030 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422031 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402032 };
2033
[email protected]5ecc992a42009-11-11 01:41:592034 StaticSocketDataProvider data(data_reads, NULL);
2035 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402036
2037 TestCompletionCallback callback;
2038
[email protected]684970b2009-08-14 04:54:462039 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422040 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402041
2042 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422043 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402044
[email protected]1c773ea12009-04-28 19:58:422045 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402046 EXPECT_TRUE(response != NULL);
2047
2048 EXPECT_TRUE(response->headers != NULL);
2049 std::string status_line = response->headers->GetStatusLine();
2050 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2051
[email protected]a937a06d2009-08-19 21:19:242052 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402053
2054 std::string response_data;
2055 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422056 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402057 EXPECT_EQ("hello world", response_data);
2058
2059 // Empty the current queue. This is necessary because idle sockets are
2060 // added to the connection pool asynchronously with a PostTask.
2061 MessageLoop::current()->RunAllPending();
2062
2063 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242064 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402065}
2066
[email protected]b4404c02009-04-10 16:38:522067// Make sure that we recycle a socket after a zero-length response.
2068// http://crbug.com/9880
2069TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592070 SessionDependencies session_deps;
2071 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522072
[email protected]5695b8c2009-09-30 21:36:432073 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522074
[email protected]1c773ea12009-04-28 19:58:422075 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522076 request.method = "GET";
2077 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2078 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2079 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2080 "rt=prt.2642,ol.2649,xjs.2951");
2081 request.load_flags = 0;
2082
2083 MockRead data_reads[] = {
2084 MockRead("HTTP/1.1 204 No Content\r\n"
2085 "Content-Length: 0\r\n"
2086 "Content-Type: text/html\r\n\r\n"),
2087 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422088 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522089 };
2090
[email protected]5ecc992a42009-11-11 01:41:592091 StaticSocketDataProvider data(data_reads, NULL);
2092 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522093
2094 TestCompletionCallback callback;
2095
[email protected]684970b2009-08-14 04:54:462096 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422097 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522098
2099 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422100 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522101
[email protected]1c773ea12009-04-28 19:58:422102 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522103 EXPECT_TRUE(response != NULL);
2104
2105 EXPECT_TRUE(response->headers != NULL);
2106 std::string status_line = response->headers->GetStatusLine();
2107 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2108
[email protected]a937a06d2009-08-19 21:19:242109 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522110
2111 std::string response_data;
2112 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422113 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522114 EXPECT_EQ("", response_data);
2115
2116 // Empty the current queue. This is necessary because idle sockets are
2117 // added to the connection pool asynchronously with a PostTask.
2118 MessageLoop::current()->RunAllPending();
2119
2120 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242121 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522122}
2123
[email protected]372d34a2008-11-05 21:30:512124TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422125 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512126 // Transaction 1: a GET request that succeeds. The socket is recycled
2127 // after use.
2128 request[0].method = "GET";
2129 request[0].url = GURL("http://www.google.com/");
2130 request[0].load_flags = 0;
2131 // Transaction 2: a POST request. Reuses the socket kept alive from
2132 // transaction 1. The first attempts fails when writing the POST data.
2133 // This causes the transaction to retry with a new socket. The second
2134 // attempt succeeds.
2135 request[1].method = "POST";
2136 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422137 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512138 request[1].upload_data->AppendBytes("foo", 3);
2139 request[1].load_flags = 0;
2140
[email protected]228ff742009-06-05 01:19:592141 SessionDependencies session_deps;
2142 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512143
2144 // The first socket is used for transaction 1 and the first attempt of
2145 // transaction 2.
2146
2147 // The response of transaction 1.
2148 MockRead data_reads1[] = {
2149 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2150 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422151 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512152 };
2153 // The mock write results of transaction 1 and the first attempt of
2154 // transaction 2.
2155 MockWrite data_writes1[] = {
2156 MockWrite(false, 64), // GET
2157 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422158 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512159 };
[email protected]5ecc992a42009-11-11 01:41:592160 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:512161
2162 // The second socket is used for the second attempt of transaction 2.
2163
2164 // The response of transaction 2.
2165 MockRead data_reads2[] = {
2166 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2167 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422168 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512169 };
2170 // The mock write results of the second attempt of transaction 2.
2171 MockWrite data_writes2[] = {
2172 MockWrite(false, 93), // POST
2173 MockWrite(false, 3), // POST data
2174 };
[email protected]5ecc992a42009-11-11 01:41:592175 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:512176
[email protected]5ecc992a42009-11-11 01:41:592177 session_deps.socket_factory.AddSocketDataProvider(&data1);
2178 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512179
2180 const char* kExpectedResponseData[] = {
2181 "hello world", "welcome"
2182 };
2183
2184 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422185 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432186 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512187
2188 TestCompletionCallback callback;
2189
[email protected]684970b2009-08-14 04:54:462190 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422191 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512192
2193 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422194 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512195
[email protected]1c773ea12009-04-28 19:58:422196 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512197 EXPECT_TRUE(response != NULL);
2198
2199 EXPECT_TRUE(response->headers != NULL);
2200 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2201
2202 std::string response_data;
2203 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422204 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512205 EXPECT_EQ(kExpectedResponseData[i], response_data);
2206 }
2207}
[email protected]f9ee6b52008-11-08 06:46:232208
2209// Test the request-challenge-retry sequence for basic auth when there is
2210// an identity in the URL. The request should be sent as normal, but when
2211// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322212TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592213 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402214 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432215 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232216
[email protected]1c773ea12009-04-28 19:58:422217 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232218 request.method = "GET";
2219 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292220 request.url = GURL("http://foo:b@[email protected]/");
2221
2222 // The password contains an escaped character -- for this test to pass it
2223 // will need to be unescaped by HttpNetworkTransaction.
2224 EXPECT_EQ("b%40r", request.url.password());
2225
[email protected]ea9dc9a2009-09-05 00:43:322226 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232227
2228 MockWrite data_writes1[] = {
2229 MockWrite("GET / HTTP/1.1\r\n"
2230 "Host: www.google.com\r\n"
2231 "Connection: keep-alive\r\n\r\n"),
2232 };
2233
2234 MockRead data_reads1[] = {
2235 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2236 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2237 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422238 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232239 };
2240
2241 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322242 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232243 MockWrite data_writes2[] = {
2244 MockWrite("GET / HTTP/1.1\r\n"
2245 "Host: www.google.com\r\n"
2246 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292247 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232248 };
2249
2250 MockRead data_reads2[] = {
2251 MockRead("HTTP/1.0 200 OK\r\n"),
2252 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422253 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232254 };
2255
[email protected]5ecc992a42009-11-11 01:41:592256 StaticSocketDataProvider data1(data_reads1, data_writes1);
2257 StaticSocketDataProvider data2(data_reads2, data_writes2);
2258 session_deps.socket_factory.AddSocketDataProvider(&data1);
2259 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232260
2261 TestCompletionCallback callback1;
2262
[email protected]684970b2009-08-14 04:54:462263 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422264 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232265
2266 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422267 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232268
[email protected]0757e7702009-03-27 04:00:222269 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2270 TestCompletionCallback callback2;
2271 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422272 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222273 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422274 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222275 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2276
[email protected]1c773ea12009-04-28 19:58:422277 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232278 EXPECT_FALSE(response == NULL);
2279
2280 // There is no challenge info, since the identity in URL worked.
2281 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2282
2283 EXPECT_EQ(100, response->headers->GetContentLength());
2284
2285 // Empty the current queue.
2286 MessageLoop::current()->RunAllPending();
2287}
2288
[email protected]ea9dc9a2009-09-05 00:43:322289// Test the request-challenge-retry sequence for basic auth when there is
2290// an incorrect identity in the URL. The identity from the URL should be used
2291// only once.
2292TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2293 SessionDependencies session_deps;
2294 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432295 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322296
2297 HttpRequestInfo request;
2298 request.method = "GET";
2299 // Note: the URL has a username:password in it. The password "baz" is
2300 // wrong (should be "bar").
2301 request.url = GURL("http://foo:[email protected]/");
2302
2303 request.load_flags = LOAD_NORMAL;
2304
2305 MockWrite data_writes1[] = {
2306 MockWrite("GET / HTTP/1.1\r\n"
2307 "Host: www.google.com\r\n"
2308 "Connection: keep-alive\r\n\r\n"),
2309 };
2310
2311 MockRead data_reads1[] = {
2312 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2313 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2314 MockRead("Content-Length: 10\r\n\r\n"),
2315 MockRead(false, ERR_FAILED),
2316 };
2317
2318 // After the challenge above, the transaction will be restarted using the
2319 // identity from the url (foo, baz) to answer the challenge.
2320 MockWrite data_writes2[] = {
2321 MockWrite("GET / HTTP/1.1\r\n"
2322 "Host: www.google.com\r\n"
2323 "Connection: keep-alive\r\n"
2324 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2325 };
2326
2327 MockRead data_reads2[] = {
2328 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2329 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2330 MockRead("Content-Length: 10\r\n\r\n"),
2331 MockRead(false, ERR_FAILED),
2332 };
2333
2334 // After the challenge above, the transaction will be restarted using the
2335 // identity supplied by the user (foo, bar) to answer the challenge.
2336 MockWrite data_writes3[] = {
2337 MockWrite("GET / HTTP/1.1\r\n"
2338 "Host: www.google.com\r\n"
2339 "Connection: keep-alive\r\n"
2340 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2341 };
2342
2343 MockRead data_reads3[] = {
2344 MockRead("HTTP/1.0 200 OK\r\n"),
2345 MockRead("Content-Length: 100\r\n\r\n"),
2346 MockRead(false, OK),
2347 };
2348
[email protected]5ecc992a42009-11-11 01:41:592349 StaticSocketDataProvider data1(data_reads1, data_writes1);
2350 StaticSocketDataProvider data2(data_reads2, data_writes2);
2351 StaticSocketDataProvider data3(data_reads3, data_writes3);
2352 session_deps.socket_factory.AddSocketDataProvider(&data1);
2353 session_deps.socket_factory.AddSocketDataProvider(&data2);
2354 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322355
2356 TestCompletionCallback callback1;
2357
2358 int rv = trans->Start(&request, &callback1, NULL);
2359 EXPECT_EQ(ERR_IO_PENDING, rv);
2360
2361 rv = callback1.WaitForResult();
2362 EXPECT_EQ(OK, rv);
2363
2364 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2365 TestCompletionCallback callback2;
2366 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2367 EXPECT_EQ(ERR_IO_PENDING, rv);
2368 rv = callback2.WaitForResult();
2369 EXPECT_EQ(OK, rv);
2370 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2371
2372 const HttpResponseInfo* response = trans->GetResponseInfo();
2373 EXPECT_FALSE(response == NULL);
2374 // The password prompt info should have been set in response->auth_challenge.
2375 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2376
2377 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2378 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2379 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2380
2381 TestCompletionCallback callback3;
2382 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2383 EXPECT_EQ(ERR_IO_PENDING, rv);
2384 rv = callback3.WaitForResult();
2385 EXPECT_EQ(OK, rv);
2386 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2387
2388 response = trans->GetResponseInfo();
2389 EXPECT_FALSE(response == NULL);
2390
2391 // There is no challenge info, since the identity worked.
2392 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2393
2394 EXPECT_EQ(100, response->headers->GetContentLength());
2395
2396 // Empty the current queue.
2397 MessageLoop::current()->RunAllPending();
2398}
2399
[email protected]f9ee6b52008-11-08 06:46:232400// Test that previously tried username/passwords for a realm get re-used.
2401TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592402 SessionDependencies session_deps;
2403 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232404
2405 // Transaction 1: authenticate (foo, bar) on MyRealm1
2406 {
[email protected]5695b8c2009-09-30 21:36:432407 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232408
[email protected]1c773ea12009-04-28 19:58:422409 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232410 request.method = "GET";
2411 request.url = GURL("http://www.google.com/x/y/z");
2412 request.load_flags = 0;
2413
2414 MockWrite data_writes1[] = {
2415 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2416 "Host: www.google.com\r\n"
2417 "Connection: keep-alive\r\n\r\n"),
2418 };
2419
2420 MockRead data_reads1[] = {
2421 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2422 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2423 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422424 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232425 };
2426
2427 // Resend with authorization (username=foo, password=bar)
2428 MockWrite data_writes2[] = {
2429 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2430 "Host: www.google.com\r\n"
2431 "Connection: keep-alive\r\n"
2432 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2433 };
2434
2435 // Sever accepts the authorization.
2436 MockRead data_reads2[] = {
2437 MockRead("HTTP/1.0 200 OK\r\n"),
2438 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422439 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232440 };
2441
[email protected]5ecc992a42009-11-11 01:41:592442 StaticSocketDataProvider data1(data_reads1, data_writes1);
2443 StaticSocketDataProvider data2(data_reads2, data_writes2);
2444 session_deps.socket_factory.AddSocketDataProvider(&data1);
2445 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232446
2447 TestCompletionCallback callback1;
2448
[email protected]684970b2009-08-14 04:54:462449 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422450 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232451
2452 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422453 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232454
[email protected]1c773ea12009-04-28 19:58:422455 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232456 EXPECT_FALSE(response == NULL);
2457
2458 // The password prompt info should have been set in
2459 // response->auth_challenge.
2460 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2461
[email protected]71e4573a2009-05-21 22:03:002462 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232463 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2464 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2465
2466 TestCompletionCallback callback2;
2467
2468 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422469 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232470
2471 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422472 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232473
2474 response = trans->GetResponseInfo();
2475 EXPECT_FALSE(response == NULL);
2476 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2477 EXPECT_EQ(100, response->headers->GetContentLength());
2478 }
2479
2480 // ------------------------------------------------------------------------
2481
2482 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2483 {
[email protected]5695b8c2009-09-30 21:36:432484 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232485
[email protected]1c773ea12009-04-28 19:58:422486 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232487 request.method = "GET";
2488 // Note that Transaction 1 was at /x/y/z, so this is in the same
2489 // protection space as MyRealm1.
2490 request.url = GURL("http://www.google.com/x/y/a/b");
2491 request.load_flags = 0;
2492
2493 MockWrite data_writes1[] = {
2494 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2495 "Host: www.google.com\r\n"
2496 "Connection: keep-alive\r\n"
2497 // Send preemptive authorization for MyRealm1
2498 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2499 };
2500
2501 // The server didn't like the preemptive authorization, and
2502 // challenges us for a different realm (MyRealm2).
2503 MockRead data_reads1[] = {
2504 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2505 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2506 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422507 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232508 };
2509
2510 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2511 MockWrite data_writes2[] = {
2512 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2513 "Host: www.google.com\r\n"
2514 "Connection: keep-alive\r\n"
2515 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2516 };
2517
2518 // Sever accepts the authorization.
2519 MockRead data_reads2[] = {
2520 MockRead("HTTP/1.0 200 OK\r\n"),
2521 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422522 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232523 };
2524
[email protected]5ecc992a42009-11-11 01:41:592525 StaticSocketDataProvider data1(data_reads1, data_writes1);
2526 StaticSocketDataProvider data2(data_reads2, data_writes2);
2527 session_deps.socket_factory.AddSocketDataProvider(&data1);
2528 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232529
2530 TestCompletionCallback callback1;
2531
[email protected]684970b2009-08-14 04:54:462532 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422533 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232534
2535 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422536 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232537
[email protected]1c773ea12009-04-28 19:58:422538 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232539 EXPECT_FALSE(response == NULL);
2540
2541 // The password prompt info should have been set in
2542 // response->auth_challenge.
2543 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2544
[email protected]71e4573a2009-05-21 22:03:002545 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232546 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2547 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2548
2549 TestCompletionCallback callback2;
2550
2551 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422552 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232553
2554 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422555 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232556
2557 response = trans->GetResponseInfo();
2558 EXPECT_FALSE(response == NULL);
2559 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2560 EXPECT_EQ(100, response->headers->GetContentLength());
2561 }
2562
2563 // ------------------------------------------------------------------------
2564
2565 // Transaction 3: Resend a request in MyRealm's protection space --
2566 // succeed with preemptive authorization.
2567 {
[email protected]5695b8c2009-09-30 21:36:432568 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232569
[email protected]1c773ea12009-04-28 19:58:422570 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232571 request.method = "GET";
2572 request.url = GURL("http://www.google.com/x/y/z2");
2573 request.load_flags = 0;
2574
2575 MockWrite data_writes1[] = {
2576 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2577 "Host: www.google.com\r\n"
2578 "Connection: keep-alive\r\n"
2579 // The authorization for MyRealm1 gets sent preemptively
2580 // (since the url is in the same protection space)
2581 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2582 };
2583
2584 // Sever accepts the preemptive authorization
2585 MockRead data_reads1[] = {
2586 MockRead("HTTP/1.0 200 OK\r\n"),
2587 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422588 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232589 };
2590
[email protected]5ecc992a42009-11-11 01:41:592591 StaticSocketDataProvider data1(data_reads1, data_writes1);
2592 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232593
2594 TestCompletionCallback callback1;
2595
[email protected]684970b2009-08-14 04:54:462596 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422597 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232598
2599 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422600 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232601
[email protected]1c773ea12009-04-28 19:58:422602 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232603 EXPECT_FALSE(response == NULL);
2604
2605 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2606 EXPECT_EQ(100, response->headers->GetContentLength());
2607 }
2608
2609 // ------------------------------------------------------------------------
2610
2611 // Transaction 4: request another URL in MyRealm (however the
2612 // url is not known to belong to the protection space, so no pre-auth).
2613 {
[email protected]5695b8c2009-09-30 21:36:432614 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232615
[email protected]1c773ea12009-04-28 19:58:422616 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232617 request.method = "GET";
2618 request.url = GURL("http://www.google.com/x/1");
2619 request.load_flags = 0;
2620
2621 MockWrite data_writes1[] = {
2622 MockWrite("GET /x/1 HTTP/1.1\r\n"
2623 "Host: www.google.com\r\n"
2624 "Connection: keep-alive\r\n\r\n"),
2625 };
2626
2627 MockRead data_reads1[] = {
2628 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2629 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2630 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422631 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232632 };
2633
2634 // Resend with authorization from MyRealm's cache.
2635 MockWrite data_writes2[] = {
2636 MockWrite("GET /x/1 HTTP/1.1\r\n"
2637 "Host: www.google.com\r\n"
2638 "Connection: keep-alive\r\n"
2639 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2640 };
2641
2642 // Sever accepts the authorization.
2643 MockRead data_reads2[] = {
2644 MockRead("HTTP/1.0 200 OK\r\n"),
2645 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422646 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232647 };
2648
[email protected]5ecc992a42009-11-11 01:41:592649 StaticSocketDataProvider data1(data_reads1, data_writes1);
2650 StaticSocketDataProvider data2(data_reads2, data_writes2);
2651 session_deps.socket_factory.AddSocketDataProvider(&data1);
2652 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232653
2654 TestCompletionCallback callback1;
2655
[email protected]684970b2009-08-14 04:54:462656 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422657 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232658
2659 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422660 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232661
[email protected]0757e7702009-03-27 04:00:222662 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2663 TestCompletionCallback callback2;
2664 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422665 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222666 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422667 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222668 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2669
[email protected]1c773ea12009-04-28 19:58:422670 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232671 EXPECT_FALSE(response == NULL);
2672 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2673 EXPECT_EQ(100, response->headers->GetContentLength());
2674 }
2675
2676 // ------------------------------------------------------------------------
2677
2678 // Transaction 5: request a URL in MyRealm, but the server rejects the
2679 // cached identity. Should invalidate and re-prompt.
2680 {
[email protected]5695b8c2009-09-30 21:36:432681 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232682
[email protected]1c773ea12009-04-28 19:58:422683 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232684 request.method = "GET";
2685 request.url = GURL("http://www.google.com/p/q/t");
2686 request.load_flags = 0;
2687
2688 MockWrite data_writes1[] = {
2689 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2690 "Host: www.google.com\r\n"
2691 "Connection: keep-alive\r\n\r\n"),
2692 };
2693
2694 MockRead data_reads1[] = {
2695 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2696 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2697 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422698 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232699 };
2700
2701 // Resend with authorization from cache for MyRealm.
2702 MockWrite data_writes2[] = {
2703 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2704 "Host: www.google.com\r\n"
2705 "Connection: keep-alive\r\n"
2706 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2707 };
2708
2709 // Sever rejects the authorization.
2710 MockRead data_reads2[] = {
2711 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2712 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2713 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422714 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232715 };
2716
2717 // At this point we should prompt for new credentials for MyRealm.
2718 // Restart with username=foo3, password=foo4.
2719 MockWrite data_writes3[] = {
2720 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2721 "Host: www.google.com\r\n"
2722 "Connection: keep-alive\r\n"
2723 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2724 };
2725
2726 // Sever accepts the authorization.
2727 MockRead data_reads3[] = {
2728 MockRead("HTTP/1.0 200 OK\r\n"),
2729 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422730 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232731 };
2732
[email protected]5ecc992a42009-11-11 01:41:592733 StaticSocketDataProvider data1(data_reads1, data_writes1);
2734 StaticSocketDataProvider data2(data_reads2, data_writes2);
2735 StaticSocketDataProvider data3(data_reads3, data_writes3);
2736 session_deps.socket_factory.AddSocketDataProvider(&data1);
2737 session_deps.socket_factory.AddSocketDataProvider(&data2);
2738 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232739
2740 TestCompletionCallback callback1;
2741
[email protected]684970b2009-08-14 04:54:462742 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422743 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232744
2745 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422746 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232747
[email protected]0757e7702009-03-27 04:00:222748 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2749 TestCompletionCallback callback2;
2750 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422751 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222752 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422753 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222754 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2755
[email protected]1c773ea12009-04-28 19:58:422756 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232757 EXPECT_FALSE(response == NULL);
2758
2759 // The password prompt info should have been set in
2760 // response->auth_challenge.
2761 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2762
[email protected]71e4573a2009-05-21 22:03:002763 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232764 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2765 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2766
[email protected]0757e7702009-03-27 04:00:222767 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232768
[email protected]0757e7702009-03-27 04:00:222769 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422770 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232771
[email protected]0757e7702009-03-27 04:00:222772 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422773 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232774
2775 response = trans->GetResponseInfo();
2776 EXPECT_FALSE(response == NULL);
2777 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2778 EXPECT_EQ(100, response->headers->GetContentLength());
2779 }
2780}
[email protected]89ceba9a2009-03-21 03:46:062781
2782// Test the ResetStateForRestart() private method.
2783TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2784 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592785 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402786 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432787 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062788
2789 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062790 trans->read_buf_ = new IOBuffer(15);
2791 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572792 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062793
2794 // Setup state in response_
[email protected]0877e3d2009-10-17 22:29:572795 trans->http_stream_.reset(new HttpBasicStream(NULL));
2796 HttpResponseInfo* response = trans->http_stream_->GetResponseInfo();
2797 response->auth_challenge = new AuthChallengeInfo();
2798 response->ssl_info.cert_status = -15;
2799 response->response_time = base::Time::Now();
2800 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062801
2802 { // Setup state for response_.vary_data
2803 HttpRequestInfo request;
2804 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2805 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:572806 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]89ceba9a2009-03-21 03:46:062807 request.extra_headers = "Foo: 1\nbar: 23";
[email protected]0877e3d2009-10-17 22:29:572808 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:062809 }
2810
2811 // Cause the above state to be reset.
2812 trans->ResetStateForRestart();
2813
2814 // Verify that the state that needed to be reset, has been reset.
[email protected]0877e3d2009-10-17 22:29:572815 response = trans->http_stream_->GetResponseInfo();
[email protected]9b6fee12009-09-29 18:13:072816 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:062817 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:572818 EXPECT_EQ(0U, trans->request_headers_.size());
2819 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2820 EXPECT_TRUE(response->headers.get() == NULL);
2821 EXPECT_EQ(false, response->was_cached);
2822 EXPECT_EQ(0, response->ssl_info.cert_status);
2823 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:062824}
2825
[email protected]bacff652009-03-31 17:50:332826// Test HTTPS connections to a site with a bad certificate
2827TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592828 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402829 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432830 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332831
2832 HttpRequestInfo request;
2833 request.method = "GET";
2834 request.url = GURL("https://www.google.com/");
2835 request.load_flags = 0;
2836
2837 MockWrite data_writes[] = {
2838 MockWrite("GET / HTTP/1.1\r\n"
2839 "Host: www.google.com\r\n"
2840 "Connection: keep-alive\r\n\r\n"),
2841 };
2842
2843 MockRead data_reads[] = {
2844 MockRead("HTTP/1.0 200 OK\r\n"),
2845 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2846 MockRead("Content-Length: 100\r\n\r\n"),
2847 MockRead(false, OK),
2848 };
2849
[email protected]5ecc992a42009-11-11 01:41:592850 StaticSocketDataProvider ssl_bad_certificate;
2851 StaticSocketDataProvider data(data_reads, data_writes);
2852 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2853 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:332854
[email protected]5ecc992a42009-11-11 01:41:592855 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2856 session_deps.socket_factory.AddSocketDataProvider(&data);
2857 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2858 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:332859
2860 TestCompletionCallback callback;
2861
[email protected]684970b2009-08-14 04:54:462862 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332863 EXPECT_EQ(ERR_IO_PENDING, rv);
2864
2865 rv = callback.WaitForResult();
2866 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2867
2868 rv = trans->RestartIgnoringLastError(&callback);
2869 EXPECT_EQ(ERR_IO_PENDING, rv);
2870
2871 rv = callback.WaitForResult();
2872 EXPECT_EQ(OK, rv);
2873
2874 const HttpResponseInfo* response = trans->GetResponseInfo();
2875
2876 EXPECT_FALSE(response == NULL);
2877 EXPECT_EQ(100, response->headers->GetContentLength());
2878}
2879
2880// Test HTTPS connections to a site with a bad certificate, going through a
2881// proxy
2882TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592883 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332884
2885 HttpRequestInfo request;
2886 request.method = "GET";
2887 request.url = GURL("https://www.google.com/");
2888 request.load_flags = 0;
2889
2890 MockWrite proxy_writes[] = {
2891 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452892 "Host: www.google.com\r\n"
2893 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332894 };
2895
2896 MockRead proxy_reads[] = {
2897 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422898 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:332899 };
2900
2901 MockWrite data_writes[] = {
2902 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452903 "Host: www.google.com\r\n"
2904 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332905 MockWrite("GET / HTTP/1.1\r\n"
2906 "Host: www.google.com\r\n"
2907 "Connection: keep-alive\r\n\r\n"),
2908 };
2909
2910 MockRead data_reads[] = {
2911 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
2912 MockRead("HTTP/1.0 200 OK\r\n"),
2913 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2914 MockRead("Content-Length: 100\r\n\r\n"),
2915 MockRead(false, OK),
2916 };
2917
[email protected]5ecc992a42009-11-11 01:41:592918 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
2919 StaticSocketDataProvider data(data_reads, data_writes);
2920 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2921 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:332922
[email protected]5ecc992a42009-11-11 01:41:592923 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2924 session_deps.socket_factory.AddSocketDataProvider(&data);
2925 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2926 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:332927
2928 TestCompletionCallback callback;
2929
2930 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:592931 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:332932
[email protected]d207a5f2009-06-04 05:28:402933 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432934 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332935
[email protected]684970b2009-08-14 04:54:462936 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332937 EXPECT_EQ(ERR_IO_PENDING, rv);
2938
2939 rv = callback.WaitForResult();
2940 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2941
2942 rv = trans->RestartIgnoringLastError(&callback);
2943 EXPECT_EQ(ERR_IO_PENDING, rv);
2944
2945 rv = callback.WaitForResult();
2946 EXPECT_EQ(OK, rv);
2947
2948 const HttpResponseInfo* response = trans->GetResponseInfo();
2949
2950 EXPECT_FALSE(response == NULL);
2951 EXPECT_EQ(100, response->headers->GetContentLength());
2952 }
2953}
2954
[email protected]1c773ea12009-04-28 19:58:422955TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:592956 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402957 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432958 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:422959
2960 HttpRequestInfo request;
2961 request.method = "GET";
2962 request.url = GURL("http://www.google.com/");
2963 request.user_agent = "Chromium Ultra Awesome X Edition";
2964
2965 MockWrite data_writes[] = {
2966 MockWrite("GET / HTTP/1.1\r\n"
2967 "Host: www.google.com\r\n"
2968 "Connection: keep-alive\r\n"
2969 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
2970 };
2971
2972 // Lastly, the server responds with the actual content.
2973 MockRead data_reads[] = {
2974 MockRead("HTTP/1.0 200 OK\r\n"),
2975 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2976 MockRead("Content-Length: 100\r\n\r\n"),
2977 MockRead(false, OK),
2978 };
2979
[email protected]5ecc992a42009-11-11 01:41:592980 StaticSocketDataProvider data(data_reads, data_writes);
2981 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:422982
2983 TestCompletionCallback callback;
2984
[email protected]684970b2009-08-14 04:54:462985 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422986 EXPECT_EQ(ERR_IO_PENDING, rv);
2987
2988 rv = callback.WaitForResult();
2989 EXPECT_EQ(OK, rv);
2990}
2991
2992TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:592993 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402994 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432995 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:422996
2997 HttpRequestInfo request;
2998 request.method = "GET";
2999 request.url = GURL("http://www.google.com/");
3000 request.load_flags = 0;
3001 request.referrer = GURL("http://the.previous.site.com/");
3002
3003 MockWrite data_writes[] = {
3004 MockWrite("GET / HTTP/1.1\r\n"
3005 "Host: www.google.com\r\n"
3006 "Connection: keep-alive\r\n"
3007 "Referer: http://the.previous.site.com/\r\n\r\n"),
3008 };
3009
3010 // Lastly, the server responds with the actual content.
3011 MockRead data_reads[] = {
3012 MockRead("HTTP/1.0 200 OK\r\n"),
3013 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3014 MockRead("Content-Length: 100\r\n\r\n"),
3015 MockRead(false, OK),
3016 };
3017
[email protected]5ecc992a42009-11-11 01:41:593018 StaticSocketDataProvider data(data_reads, data_writes);
3019 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423020
3021 TestCompletionCallback callback;
3022
[email protected]684970b2009-08-14 04:54:463023 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423024 EXPECT_EQ(ERR_IO_PENDING, rv);
3025
3026 rv = callback.WaitForResult();
3027 EXPECT_EQ(OK, rv);
3028}
3029
3030TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593031 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403032 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433033 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423034
3035 HttpRequestInfo request;
3036 request.method = "POST";
3037 request.url = GURL("http://www.google.com/");
3038
3039 MockWrite data_writes[] = {
3040 MockWrite("POST / HTTP/1.1\r\n"
3041 "Host: www.google.com\r\n"
3042 "Connection: keep-alive\r\n"
3043 "Content-Length: 0\r\n\r\n"),
3044 };
3045
3046 // Lastly, the server responds with the actual content.
3047 MockRead data_reads[] = {
3048 MockRead("HTTP/1.0 200 OK\r\n"),
3049 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3050 MockRead("Content-Length: 100\r\n\r\n"),
3051 MockRead(false, OK),
3052 };
3053
[email protected]5ecc992a42009-11-11 01:41:593054 StaticSocketDataProvider data(data_reads, data_writes);
3055 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423056
3057 TestCompletionCallback callback;
3058
[email protected]684970b2009-08-14 04:54:463059 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423060 EXPECT_EQ(ERR_IO_PENDING, rv);
3061
3062 rv = callback.WaitForResult();
3063 EXPECT_EQ(OK, rv);
3064}
3065
3066TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593067 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403068 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433069 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423070
3071 HttpRequestInfo request;
3072 request.method = "PUT";
3073 request.url = GURL("http://www.google.com/");
3074
3075 MockWrite data_writes[] = {
3076 MockWrite("PUT / HTTP/1.1\r\n"
3077 "Host: www.google.com\r\n"
3078 "Connection: keep-alive\r\n"
3079 "Content-Length: 0\r\n\r\n"),
3080 };
3081
3082 // Lastly, the server responds with the actual content.
3083 MockRead data_reads[] = {
3084 MockRead("HTTP/1.0 200 OK\r\n"),
3085 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3086 MockRead("Content-Length: 100\r\n\r\n"),
3087 MockRead(false, OK),
3088 };
3089
[email protected]5ecc992a42009-11-11 01:41:593090 StaticSocketDataProvider data(data_reads, data_writes);
3091 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423092
3093 TestCompletionCallback callback;
3094
[email protected]684970b2009-08-14 04:54:463095 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423096 EXPECT_EQ(ERR_IO_PENDING, rv);
3097
3098 rv = callback.WaitForResult();
3099 EXPECT_EQ(OK, rv);
3100}
3101
3102TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593103 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403104 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433105 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423106
3107 HttpRequestInfo request;
3108 request.method = "HEAD";
3109 request.url = GURL("http://www.google.com/");
3110
3111 MockWrite data_writes[] = {
3112 MockWrite("HEAD / HTTP/1.1\r\n"
3113 "Host: www.google.com\r\n"
3114 "Connection: keep-alive\r\n"
3115 "Content-Length: 0\r\n\r\n"),
3116 };
3117
3118 // Lastly, the server responds with the actual content.
3119 MockRead data_reads[] = {
3120 MockRead("HTTP/1.0 200 OK\r\n"),
3121 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3122 MockRead("Content-Length: 100\r\n\r\n"),
3123 MockRead(false, OK),
3124 };
3125
[email protected]5ecc992a42009-11-11 01:41:593126 StaticSocketDataProvider data(data_reads, data_writes);
3127 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423128
3129 TestCompletionCallback callback;
3130
[email protected]684970b2009-08-14 04:54:463131 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423132 EXPECT_EQ(ERR_IO_PENDING, rv);
3133
3134 rv = callback.WaitForResult();
3135 EXPECT_EQ(OK, rv);
3136}
3137
3138TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593139 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403140 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433141 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423142
3143 HttpRequestInfo request;
3144 request.method = "GET";
3145 request.url = GURL("http://www.google.com/");
3146 request.load_flags = LOAD_BYPASS_CACHE;
3147
3148 MockWrite data_writes[] = {
3149 MockWrite("GET / HTTP/1.1\r\n"
3150 "Host: www.google.com\r\n"
3151 "Connection: keep-alive\r\n"
3152 "Pragma: no-cache\r\n"
3153 "Cache-Control: no-cache\r\n\r\n"),
3154 };
3155
3156 // Lastly, the server responds with the actual content.
3157 MockRead data_reads[] = {
3158 MockRead("HTTP/1.0 200 OK\r\n"),
3159 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3160 MockRead("Content-Length: 100\r\n\r\n"),
3161 MockRead(false, OK),
3162 };
3163
[email protected]5ecc992a42009-11-11 01:41:593164 StaticSocketDataProvider data(data_reads, data_writes);
3165 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423166
3167 TestCompletionCallback callback;
3168
[email protected]684970b2009-08-14 04:54:463169 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423170 EXPECT_EQ(ERR_IO_PENDING, rv);
3171
3172 rv = callback.WaitForResult();
3173 EXPECT_EQ(OK, rv);
3174}
3175
3176TEST_F(HttpNetworkTransactionTest,
3177 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593178 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403179 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433180 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423181
3182 HttpRequestInfo request;
3183 request.method = "GET";
3184 request.url = GURL("http://www.google.com/");
3185 request.load_flags = LOAD_VALIDATE_CACHE;
3186
3187 MockWrite data_writes[] = {
3188 MockWrite("GET / HTTP/1.1\r\n"
3189 "Host: www.google.com\r\n"
3190 "Connection: keep-alive\r\n"
3191 "Cache-Control: max-age=0\r\n\r\n"),
3192 };
3193
3194 // Lastly, the server responds with the actual content.
3195 MockRead data_reads[] = {
3196 MockRead("HTTP/1.0 200 OK\r\n"),
3197 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3198 MockRead("Content-Length: 100\r\n\r\n"),
3199 MockRead(false, OK),
3200 };
3201
[email protected]5ecc992a42009-11-11 01:41:593202 StaticSocketDataProvider data(data_reads, data_writes);
3203 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423204
3205 TestCompletionCallback callback;
3206
[email protected]684970b2009-08-14 04:54:463207 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423208 EXPECT_EQ(ERR_IO_PENDING, rv);
3209
3210 rv = callback.WaitForResult();
3211 EXPECT_EQ(OK, rv);
3212}
3213
3214TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593215 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403216 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433217 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423218
3219 HttpRequestInfo request;
3220 request.method = "GET";
3221 request.url = GURL("http://www.google.com/");
3222 request.extra_headers = "FooHeader: Bar\r\n";
3223
3224 MockWrite data_writes[] = {
3225 MockWrite("GET / HTTP/1.1\r\n"
3226 "Host: www.google.com\r\n"
3227 "Connection: keep-alive\r\n"
3228 "FooHeader: Bar\r\n\r\n"),
3229 };
3230
3231 // Lastly, the server responds with the actual content.
3232 MockRead data_reads[] = {
3233 MockRead("HTTP/1.0 200 OK\r\n"),
3234 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3235 MockRead("Content-Length: 100\r\n\r\n"),
3236 MockRead(false, OK),
3237 };
3238
[email protected]5ecc992a42009-11-11 01:41:593239 StaticSocketDataProvider data(data_reads, data_writes);
3240 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423241
3242 TestCompletionCallback callback;
3243
[email protected]684970b2009-08-14 04:54:463244 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423245 EXPECT_EQ(ERR_IO_PENDING, rv);
3246
3247 rv = callback.WaitForResult();
3248 EXPECT_EQ(OK, rv);
3249}
3250
[email protected]3cd17242009-06-23 02:59:023251TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093252 SessionDependencies session_deps(
3253 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023254
3255 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433256 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023257
3258 HttpRequestInfo request;
3259 request.method = "GET";
3260 request.url = GURL("http://www.google.com/");
3261 request.load_flags = 0;
3262
3263 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3264 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3265
3266 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353267 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023268 MockWrite("GET / HTTP/1.1\r\n"
3269 "Host: www.google.com\r\n"
3270 "Connection: keep-alive\r\n\r\n")
3271 };
3272
3273 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593274 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023275 MockRead("HTTP/1.0 200 OK\r\n"),
3276 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3277 MockRead("Payload"),
3278 MockRead(false, OK)
3279 };
3280
[email protected]5ecc992a42009-11-11 01:41:593281 StaticSocketDataProvider data(data_reads, data_writes);
3282 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023283
3284 TestCompletionCallback callback;
3285
[email protected]684970b2009-08-14 04:54:463286 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023287 EXPECT_EQ(ERR_IO_PENDING, rv);
3288
3289 rv = callback.WaitForResult();
3290 EXPECT_EQ(OK, rv);
3291
3292 const HttpResponseInfo* response = trans->GetResponseInfo();
3293 EXPECT_FALSE(response == NULL);
3294
3295 std::string response_text;
3296 rv = ReadTransaction(trans.get(), &response_text);
3297 EXPECT_EQ(OK, rv);
3298 EXPECT_EQ("Payload", response_text);
3299}
3300
3301TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093302 SessionDependencies session_deps(
3303 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023304
3305 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433306 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023307
3308 HttpRequestInfo request;
3309 request.method = "GET";
3310 request.url = GURL("https://www.google.com/");
3311 request.load_flags = 0;
3312
3313 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3314 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3315
3316 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353317 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3318 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023319 MockWrite("GET / HTTP/1.1\r\n"
3320 "Host: www.google.com\r\n"
3321 "Connection: keep-alive\r\n\r\n")
3322 };
3323
3324 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353325 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3326 arraysize(read_buffer)),
3327 MockRead("HTTP/1.0 200 OK\r\n"),
3328 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3329 MockRead("Payload"),
3330 MockRead(false, OK)
3331 };
3332
[email protected]5ecc992a42009-11-11 01:41:593333 StaticSocketDataProvider data(data_reads, data_writes);
3334 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353335
[email protected]5ecc992a42009-11-11 01:41:593336 SSLSocketDataProvider ssl(true, OK);
3337 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353338
3339 TestCompletionCallback callback;
3340
[email protected]684970b2009-08-14 04:54:463341 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353342 EXPECT_EQ(ERR_IO_PENDING, rv);
3343
3344 rv = callback.WaitForResult();
3345 EXPECT_EQ(OK, rv);
3346
3347 const HttpResponseInfo* response = trans->GetResponseInfo();
3348 EXPECT_FALSE(response == NULL);
3349
3350 std::string response_text;
3351 rv = ReadTransaction(trans.get(), &response_text);
3352 EXPECT_EQ(OK, rv);
3353 EXPECT_EQ("Payload", response_text);
3354}
3355
3356TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093357 SessionDependencies session_deps(
3358 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353359
3360 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433361 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353362
3363 HttpRequestInfo request;
3364 request.method = "GET";
3365 request.url = GURL("http://www.google.com/");
3366 request.load_flags = 0;
3367
3368 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3369 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3370 const char kSOCKS5OkRequest[] =
3371 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3372 const char kSOCKS5OkResponse[] =
3373 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3374
3375 MockWrite data_writes[] = {
3376 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3377 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3378 MockWrite("GET / HTTP/1.1\r\n"
3379 "Host: www.google.com\r\n"
3380 "Connection: keep-alive\r\n\r\n")
3381 };
3382
3383 MockRead data_reads[] = {
3384 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3385 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3386 MockRead("HTTP/1.0 200 OK\r\n"),
3387 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3388 MockRead("Payload"),
3389 MockRead(false, OK)
3390 };
3391
[email protected]5ecc992a42009-11-11 01:41:593392 StaticSocketDataProvider data(data_reads, data_writes);
3393 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353394
3395 TestCompletionCallback callback;
3396
[email protected]684970b2009-08-14 04:54:463397 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353398 EXPECT_EQ(ERR_IO_PENDING, rv);
3399
3400 rv = callback.WaitForResult();
3401 EXPECT_EQ(OK, rv);
3402
3403 const HttpResponseInfo* response = trans->GetResponseInfo();
3404 EXPECT_FALSE(response == NULL);
3405
3406 std::string response_text;
3407 rv = ReadTransaction(trans.get(), &response_text);
3408 EXPECT_EQ(OK, rv);
3409 EXPECT_EQ("Payload", response_text);
3410}
3411
3412TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093413 SessionDependencies session_deps(
3414 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353415
3416 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433417 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353418
3419 HttpRequestInfo request;
3420 request.method = "GET";
3421 request.url = GURL("https://www.google.com/");
3422 request.load_flags = 0;
3423
3424 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3425 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3426 const unsigned char kSOCKS5OkRequest[] =
3427 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x01, 0xBB };
3428 const char kSOCKS5OkResponse[] =
3429 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3430
3431 MockWrite data_writes[] = {
3432 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3433 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3434 arraysize(kSOCKS5OkRequest)),
3435 MockWrite("GET / HTTP/1.1\r\n"
3436 "Host: www.google.com\r\n"
3437 "Connection: keep-alive\r\n\r\n")
3438 };
3439
3440 MockRead data_reads[] = {
3441 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3442 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023443 MockRead("HTTP/1.0 200 OK\r\n"),
3444 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3445 MockRead("Payload"),
3446 MockRead(false, OK)
3447 };
3448
[email protected]5ecc992a42009-11-11 01:41:593449 StaticSocketDataProvider data(data_reads, data_writes);
3450 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023451
[email protected]5ecc992a42009-11-11 01:41:593452 SSLSocketDataProvider ssl(true, OK);
3453 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023454
3455 TestCompletionCallback callback;
3456
[email protected]684970b2009-08-14 04:54:463457 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023458 EXPECT_EQ(ERR_IO_PENDING, rv);
3459
3460 rv = callback.WaitForResult();
3461 EXPECT_EQ(OK, rv);
3462
3463 const HttpResponseInfo* response = trans->GetResponseInfo();
3464 EXPECT_FALSE(response == NULL);
3465
3466 std::string response_text;
3467 rv = ReadTransaction(trans.get(), &response_text);
3468 EXPECT_EQ(OK, rv);
3469 EXPECT_EQ("Payload", response_text);
3470}
3471
[email protected]04e5be32009-06-26 20:00:313472// Tests that for connection endpoints the group names are correctly set.
3473TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3474 const struct {
3475 const std::string proxy_server;
3476 const std::string url;
3477 const std::string expected_group_name;
3478 } tests[] = {
3479 {
3480 "", // no proxy (direct)
3481 "http://www.google.com/direct",
3482 "http://www.google.com/",
3483 },
3484 {
3485 "http_proxy",
3486 "http://www.google.com/http_proxy_normal",
3487 "proxy/http_proxy:80/",
3488 },
3489 {
3490 "socks4://socks_proxy:1080",
3491 "http://www.google.com/socks4_direct",
3492 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3493 },
3494
3495 // SSL Tests
3496 {
3497 "",
3498 "https://www.google.com/direct_ssl",
3499 "https://www.google.com/",
3500 },
3501 {
3502 "http_proxy",
3503 "https://www.google.com/http_connect_ssl",
3504 "proxy/http_proxy:80/https://www.google.com/",
3505 },
3506 {
3507 "socks4://socks_proxy:1080",
3508 "https://www.google.com/socks4_ssl",
3509 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3510 },
3511 };
3512
3513 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093514 SessionDependencies session_deps(
3515 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313516
3517 scoped_refptr<CaptureGroupNameSocketPool> conn_pool(
3518 new CaptureGroupNameSocketPool());
3519
3520 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a937a06d2009-08-19 21:19:243521 session->tcp_socket_pool_ = conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313522
[email protected]5695b8c2009-09-30 21:36:433523 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313524
3525 HttpRequestInfo request;
3526 request.method = "GET";
3527 request.url = GURL(tests[i].url);
3528 request.load_flags = 0;
3529
3530 TestCompletionCallback callback;
3531
3532 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463533 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]04e5be32009-06-26 20:00:313534 EXPECT_EQ(tests[i].expected_group_name,
3535 conn_pool->last_group_name_received());
3536 }
3537}
3538
[email protected]9172a982009-06-06 00:30:253539TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543540 SessionDependencies session_deps(
3541 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323542
3543 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3544
[email protected]9172a982009-06-06 00:30:253545 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433546 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253547
3548 HttpRequestInfo request;
3549 request.method = "GET";
3550 request.url = GURL("http://www.google.com/");
3551
3552 TestCompletionCallback callback;
3553
[email protected]684970b2009-08-14 04:54:463554 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253555 EXPECT_EQ(ERR_IO_PENDING, rv);
3556
[email protected]9172a982009-06-06 00:30:253557 rv = callback.WaitForResult();
3558 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3559}
3560
[email protected]f3e6c1e2009-06-15 20:52:123561// Host resolution observer used by
3562// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3563// resovle requests are issued with a referrer of |expected_referrer|.
3564class ResolutionReferrerObserver : public HostResolver::Observer {
3565 public:
3566 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3567 : expected_referrer_(expected_referrer),
3568 called_start_with_referrer_(false),
3569 called_finish_with_referrer_(false) {
3570 }
3571
3572 virtual void OnStartResolution(int id,
3573 const HostResolver::RequestInfo& info) {
3574 if (info.referrer() == expected_referrer_)
3575 called_start_with_referrer_ = true;
3576 }
3577
3578 virtual void OnFinishResolutionWithStatus(
3579 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3580 if (info.referrer() == expected_referrer_)
3581 called_finish_with_referrer_ = true;
3582 }
3583
[email protected]eb255d32009-06-17 02:11:033584 virtual void OnCancelResolution(int id,
3585 const HostResolver::RequestInfo& info ) {
3586 FAIL() << "Should not be cancelling any requests!";
3587 }
3588
[email protected]f3e6c1e2009-06-15 20:52:123589 bool did_complete_with_expected_referrer() const {
3590 return called_start_with_referrer_ && called_finish_with_referrer_;
3591 }
3592
3593 private:
3594 GURL expected_referrer_;
3595 bool called_start_with_referrer_;
3596 bool called_finish_with_referrer_;
3597
3598 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3599};
3600
3601// Make sure that when HostResolver::Resolve() is invoked, it passes through
3602// the "referrer". This is depended on by the DNS prefetch observer.
3603TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3604 GURL referrer = GURL("http://expected-referrer/");
3605 EXPECT_TRUE(referrer.is_valid());
3606 ResolutionReferrerObserver resolution_observer(referrer);
3607
3608 SessionDependencies session_deps;
3609 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433610 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123611
3612 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143613 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123614
3615 // Connect up a mock socket which will fail when reading.
3616 MockRead data_reads[] = {
3617 MockRead(false, ERR_FAILED),
3618 };
[email protected]5ecc992a42009-11-11 01:41:593619 StaticSocketDataProvider data(data_reads, NULL);
3620 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:123621
3622 // Issue a request, containing an HTTP referrer.
3623 HttpRequestInfo request;
3624 request.method = "GET";
3625 request.referrer = referrer;
3626 request.url = GURL("http://www.google.com/");
3627
3628 // Run the request until it fails reading from the socket.
3629 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463630 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123631 EXPECT_EQ(ERR_IO_PENDING, rv);
3632 rv = callback.WaitForResult();
3633 EXPECT_EQ(ERR_FAILED, rv);
3634
3635 // Check that the host resolution observer saw |referrer|.
3636 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3637}
3638
[email protected]3b9cca42009-06-16 01:08:283639// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3640// host cache is bypassed.
3641TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3642 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323643
[email protected]a2c2fb92009-07-18 07:31:043644 // Select a host resolver that does caching.
3645 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323646
[email protected]3b9cca42009-06-16 01:08:283647 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433648 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:283649
3650 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3651 // a synchronous lookup.)
3652 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143653 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463654 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3655 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283656 EXPECT_EQ(OK, rv);
3657
3658 // Verify that it was added to host cache, by doing a subsequent async lookup
3659 // and confirming it completes synchronously.
3660 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463661 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283662 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463663 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323664 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283665
3666 // Inject a failure the next time that "www.google.com" is resolved. This way
3667 // we can tell if the next lookup hit the cache, or the "network".
3668 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323669 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283670
3671 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3672 // first read -- this won't be reached as the host resolution will fail first.
3673 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]5ecc992a42009-11-11 01:41:593674 StaticSocketDataProvider data(data_reads, NULL);
3675 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:283676
3677 // Issue a request, asking to bypass the cache(s).
3678 HttpRequestInfo request;
3679 request.method = "GET";
3680 request.load_flags = LOAD_BYPASS_CACHE;
3681 request.url = GURL("http://www.google.com/");
3682
3683 // Run the request.
3684 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463685 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283686 ASSERT_EQ(ERR_IO_PENDING, rv);
3687 rv = callback.WaitForResult();
3688
3689 // If we bypassed the cache, we would have gotten a failure while resolving
3690 // "www.google.com".
3691 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3692}
3693
[email protected]0877e3d2009-10-17 22:29:573694// Make sure we can handle an error when writing the request.
3695TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3696 SessionDependencies session_deps;
3697 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3698
3699 HttpRequestInfo request;
3700 request.method = "GET";
3701 request.url = GURL("http://www.foo.com/");
3702 request.load_flags = 0;
3703
3704 MockWrite write_failure[] = {
3705 MockWrite(true, ERR_CONNECTION_RESET),
3706 };
[email protected]5ecc992a42009-11-11 01:41:593707 StaticSocketDataProvider data(NULL, write_failure);
3708 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573709
3710 TestCompletionCallback callback;
3711
3712 scoped_ptr<HttpTransaction> trans(
3713 new HttpNetworkTransaction(CreateSession(&session_deps)));
3714
3715 int rv = trans->Start(&request, &callback, NULL);
3716 EXPECT_EQ(ERR_IO_PENDING, rv);
3717
3718 rv = callback.WaitForResult();
3719 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3720}
3721
3722// Check that a connection closed after the start of the headers finishes ok.
3723TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3724 SessionDependencies session_deps;
3725 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3726
3727 HttpRequestInfo request;
3728 request.method = "GET";
3729 request.url = GURL("http://www.foo.com/");
3730 request.load_flags = 0;
3731
3732 MockRead data_reads[] = {
3733 MockRead("HTTP/1."),
3734 MockRead(false, OK),
3735 };
3736
[email protected]5ecc992a42009-11-11 01:41:593737 StaticSocketDataProvider data(data_reads, NULL);
3738 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573739
3740 TestCompletionCallback callback;
3741
3742 scoped_ptr<HttpTransaction> trans(
3743 new HttpNetworkTransaction(CreateSession(&session_deps)));
3744
3745 int rv = trans->Start(&request, &callback, NULL);
3746 EXPECT_EQ(ERR_IO_PENDING, rv);
3747
3748 rv = callback.WaitForResult();
3749 EXPECT_EQ(OK, rv);
3750
3751 const HttpResponseInfo* response = trans->GetResponseInfo();
3752 EXPECT_TRUE(response != NULL);
3753
3754 EXPECT_TRUE(response->headers != NULL);
3755 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
3756
3757 std::string response_data;
3758 rv = ReadTransaction(trans.get(), &response_data);
3759 EXPECT_EQ(OK, rv);
3760 EXPECT_EQ("", response_data);
3761}
3762
3763// Make sure that a dropped connection while draining the body for auth
3764// restart does the right thing.
3765TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
3766 SessionDependencies session_deps;
3767 scoped_ptr<HttpTransaction> trans(
3768 new HttpNetworkTransaction(CreateSession(&session_deps)));
3769
3770 HttpRequestInfo request;
3771 request.method = "GET";
3772 request.url = GURL("http://www.google.com/");
3773 request.load_flags = 0;
3774
3775 MockWrite data_writes1[] = {
3776 MockWrite("GET / HTTP/1.1\r\n"
3777 "Host: www.google.com\r\n"
3778 "Connection: keep-alive\r\n\r\n"),
3779 };
3780
3781 MockRead data_reads1[] = {
3782 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3783 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3784 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3785 MockRead("Content-Length: 14\r\n\r\n"),
3786 MockRead("Unauth"),
3787 MockRead(true, ERR_CONNECTION_RESET),
3788 };
3789
[email protected]5ecc992a42009-11-11 01:41:593790 StaticSocketDataProvider data1(data_reads1, data_writes1);
3791 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:573792
3793 // After calling trans->RestartWithAuth(), this is the request we should
3794 // be issuing -- the final header line contains the credentials.
3795 MockWrite data_writes2[] = {
3796 MockWrite("GET / HTTP/1.1\r\n"
3797 "Host: www.google.com\r\n"
3798 "Connection: keep-alive\r\n"
3799 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3800 };
3801
3802 // Lastly, the server responds with the actual content.
3803 MockRead data_reads2[] = {
3804 MockRead("HTTP/1.1 200 OK\r\n"),
3805 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3806 MockRead("Content-Length: 100\r\n\r\n"),
3807 MockRead(false, OK),
3808 };
3809
[email protected]5ecc992a42009-11-11 01:41:593810 StaticSocketDataProvider data2(data_reads2, data_writes2);
3811 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:573812
3813 TestCompletionCallback callback1;
3814
3815 int rv = trans->Start(&request, &callback1, NULL);
3816 EXPECT_EQ(ERR_IO_PENDING, rv);
3817
3818 rv = callback1.WaitForResult();
3819 EXPECT_EQ(OK, rv);
3820
3821 const HttpResponseInfo* response = trans->GetResponseInfo();
3822 EXPECT_FALSE(response == NULL);
3823
3824 // The password prompt info should have been set in response->auth_challenge.
3825 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3826
3827 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3828 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3829 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3830
3831 TestCompletionCallback callback2;
3832
3833 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3834 EXPECT_EQ(ERR_IO_PENDING, rv);
3835
3836 rv = callback2.WaitForResult();
3837 EXPECT_EQ(OK, rv);
3838
3839 response = trans->GetResponseInfo();
3840 EXPECT_FALSE(response == NULL);
3841 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3842 EXPECT_EQ(100, response->headers->GetContentLength());
3843}
3844
3845// Test HTTPS connections going through a proxy that sends extra data.
3846TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
3847 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
3848
3849 HttpRequestInfo request;
3850 request.method = "GET";
3851 request.url = GURL("https://www.google.com/");
3852 request.load_flags = 0;
3853
3854 MockRead proxy_reads[] = {
3855 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
3856 MockRead(false, OK)
3857 };
3858
[email protected]5ecc992a42009-11-11 01:41:593859 StaticSocketDataProvider data(proxy_reads, NULL);
3860 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:573861
[email protected]5ecc992a42009-11-11 01:41:593862 session_deps.socket_factory.AddSocketDataProvider(&data);
3863 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:573864
3865 TestCompletionCallback callback;
3866
3867 session_deps.socket_factory.ResetNextMockIndexes();
3868
3869 scoped_ptr<HttpTransaction> trans(
3870 new HttpNetworkTransaction(CreateSession(&session_deps)));
3871
3872 int rv = trans->Start(&request, &callback, NULL);
3873 EXPECT_EQ(ERR_IO_PENDING, rv);
3874
3875 rv = callback.WaitForResult();
3876 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3877}
3878
[email protected]89ceba9a2009-03-21 03:46:063879} // namespace net