blob: 1106757ba8209b2a1181da3a490a54443f9d7738 [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]ac790b42009-12-02 04:31:3110#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4211#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3312#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5213#include "net/base/test_completion_callback.h"
14#include "net/base/upload_data.h"
[email protected]d1eda932009-11-04 01:03:1015#include "net/flip/flip_session_pool.h"
[email protected]385a4672009-03-11 22:21:2916#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5717#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5218#include "net/http/http_network_session.h"
19#include "net/http/http_network_transaction.h"
[email protected]0877e3d2009-10-17 22:29:5720#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5221#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5322#include "net/proxy/proxy_config_service_fixed.h"
[email protected]f7984fc62009-06-22 23:26:4423#include "net/socket/client_socket_factory.h"
24#include "net/socket/socket_test_util.h"
25#include "net/socket/ssl_client_socket.h"
initial.commit586acc5fe2008-07-26 22:42:5226#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1527#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5228
29//-----------------------------------------------------------------------------
30
[email protected]89ceba9a2009-03-21 03:46:0631namespace net {
32
[email protected]db8f44c2008-12-13 04:52:0133// Create a proxy service which fails on all requests (falls back to direct).
[email protected]1c773ea12009-04-28 19:58:4234ProxyService* CreateNullProxyService() {
35 return ProxyService::CreateNull();
initial.commit586acc5fe2008-07-26 22:42:5236}
37
[email protected]e44de5d2009-06-05 20:12:4538// Helper to manage the lifetimes of the dependencies for a
39// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5940class SessionDependencies {
41 public:
42 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4243 SessionDependencies()
44 : host_resolver(new MockHostResolver),
45 proxy_service(CreateNullProxyService()),
[email protected]d1eda932009-11-04 01:03:1046 ssl_config_service(new SSLConfigServiceDefaults),
47 flip_session_pool(new FlipSessionPool) {}
[email protected]228ff742009-06-05 01:19:5948
49 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4550 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4251 : host_resolver(new MockHostResolver),
52 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1053 ssl_config_service(new SSLConfigServiceDefaults),
54 flip_session_pool(new FlipSessionPool) {}
[email protected]228ff742009-06-05 01:19:5955
[email protected]a2c2fb92009-07-18 07:31:0456 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0957 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4258 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5959 MockClientSocketFactory socket_factory;
[email protected]d1eda932009-11-04 01:03:1060 scoped_refptr<FlipSessionPool> flip_session_pool;
[email protected]228ff742009-06-05 01:19:5961};
62
[email protected]1c773ea12009-04-28 19:58:4263ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5064 net::ProxyConfig proxy_config;
65 proxy_config.proxy_rules.ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3966 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5367}
68
69
[email protected]228ff742009-06-05 01:19:5970HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]94a0d3d92009-06-27 01:50:1471 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:0972 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:4273 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:1074 session_deps->ssl_config_service,
75 session_deps->flip_session_pool);
[email protected]e8d536192008-10-17 22:21:1476}
77
[email protected]89836e22008-09-25 20:33:4278class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:5279 public:
[email protected]0e75a732008-10-16 20:36:0980 virtual void TearDown() {
81 // Empty the current queue.
82 MessageLoop::current()->RunAllPending();
83 PlatformTest::TearDown();
84 }
85
[email protected]3d2a59b2008-09-26 19:44:2586 protected:
87 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:5288
[email protected]ff007e162009-05-23 09:13:1589 struct SimpleGetHelperResult {
90 int rv;
91 std::string status_line;
92 std::string response_data;
93 };
initial.commit586acc5fe2008-07-26 22:42:5294
[email protected]ff007e162009-05-23 09:13:1595 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
96 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:5297
[email protected]228ff742009-06-05 01:19:5998 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:4099 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43100 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52101
[email protected]ff007e162009-05-23 09:13:15102 HttpRequestInfo request;
103 request.method = "GET";
104 request.url = GURL("http://www.google.com/");
105 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52106
[email protected]5ecc992a42009-11-11 01:41:59107 StaticSocketDataProvider data(data_reads, NULL);
108 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52109
[email protected]ff007e162009-05-23 09:13:15110 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52111
[email protected]684970b2009-08-14 04:54:46112 int rv = trans->Start(&request, &callback, NULL);
[email protected]ff007e162009-05-23 09:13:15113 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52114
[email protected]ff007e162009-05-23 09:13:15115 out.rv = callback.WaitForResult();
116 if (out.rv != OK)
117 return out;
118
119 const HttpResponseInfo* response = trans->GetResponseInfo();
120 EXPECT_TRUE(response != NULL);
121
122 EXPECT_TRUE(response->headers != NULL);
123 out.status_line = response->headers->GetStatusLine();
124
125 rv = ReadTransaction(trans.get(), &out.response_data);
126 EXPECT_EQ(OK, rv);
127
[email protected]aecfbf22008-10-16 02:02:47128 return out;
[email protected]ff007e162009-05-23 09:13:15129 }
initial.commit586acc5fe2008-07-26 22:42:52130
[email protected]ff007e162009-05-23 09:13:15131 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
132 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52133
[email protected]ff007e162009-05-23 09:13:15134 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15135};
[email protected]231d5a32008-09-13 00:45:27136
[email protected]15a5ccf82008-10-23 19:57:43137// Fill |str| with a long header list that consumes >= |size| bytes.
138void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19139 const char* row =
140 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
141 const int sizeof_row = strlen(row);
142 const int num_rows = static_cast<int>(
143 ceil(static_cast<float>(size) / sizeof_row));
144 const int sizeof_data = num_rows * sizeof_row;
145 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43146 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51147
[email protected]4ddaf2502008-10-23 18:26:19148 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43149 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19150}
151
[email protected]385a4672009-03-11 22:21:29152// Alternative functions that eliminate randomness and dependency on the local
153// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20154void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29155 static const uint8 bytes[] = {
156 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
157 };
158 static size_t current_byte = 0;
159 for (size_t i = 0; i < n; ++i) {
160 output[i] = bytes[current_byte++];
161 current_byte %= arraysize(bytes);
162 }
163}
164
[email protected]fe2bc6a2009-03-23 16:52:20165void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29166 static const uint8 bytes[] = {
167 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
168 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
169 };
170 static size_t current_byte = 0;
171 for (size_t i = 0; i < n; ++i) {
172 output[i] = bytes[current_byte++];
173 current_byte %= arraysize(bytes);
174 }
175}
176
[email protected]fe2bc6a2009-03-23 16:52:20177std::string MockGetHostName() {
178 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29179}
180
[email protected]a937a06d2009-08-19 21:19:24181class CaptureGroupNameSocketPool : public TCPClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31182 public:
[email protected]a937a06d2009-08-19 21:19:24183 CaptureGroupNameSocketPool() : TCPClientSocketPool(0, 0, NULL, NULL) {}
[email protected]d80a4322009-08-14 07:07:49184 const std::string last_group_name_received() const {
185 return last_group_name_;
186 }
187
[email protected]684970b2009-08-14 04:54:46188 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49189 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31190 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31191 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46192 CompletionCallback* callback,
193 LoadLog* load_log) {
[email protected]04e5be32009-06-26 20:00:31194 last_group_name_ = group_name;
195 return ERR_IO_PENDING;
196 }
[email protected]04e5be32009-06-26 20:00:31197 virtual void CancelRequest(const std::string& group_name,
198 const ClientSocketHandle* handle) { }
199 virtual void ReleaseSocket(const std::string& group_name,
200 ClientSocket* socket) {}
201 virtual void CloseIdleSockets() {}
202 virtual HostResolver* GetHostResolver() const {
203 return NULL;
204 }
205 virtual int IdleSocketCount() const {
206 return 0;
207 }
208 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
209 return 0;
210 }
211 virtual LoadState GetLoadState(const std::string& group_name,
212 const ClientSocketHandle* handle) const {
213 return LOAD_STATE_IDLE;
214 }
[email protected]d80a4322009-08-14 07:07:49215
216 private:
[email protected]04e5be32009-06-26 20:00:31217 std::string last_group_name_;
218};
219
[email protected]231d5a32008-09-13 00:45:27220//-----------------------------------------------------------------------------
221
222TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59223 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40224 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43225 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27226}
227
228TEST_F(HttpNetworkTransactionTest, SimpleGET) {
229 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35230 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
231 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42232 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27233 };
[email protected]231d5a32008-09-13 00:45:27234 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42235 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27236 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
237 EXPECT_EQ("hello world", out.response_data);
238}
239
240// Response with no status line.
241TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
242 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35243 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42244 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27245 };
[email protected]231d5a32008-09-13 00:45:27246 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42247 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27248 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
249 EXPECT_EQ("hello world", out.response_data);
250}
251
252// Allow up to 4 bytes of junk to precede status line.
253TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
254 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35255 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42256 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27257 };
258 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42259 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27260 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
261 EXPECT_EQ("DATA", out.response_data);
262}
263
264// Allow up to 4 bytes of junk to precede status line.
265TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
266 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35267 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42268 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27269 };
270 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42271 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27272 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
273 EXPECT_EQ("DATA", out.response_data);
274}
275
276// Beyond 4 bytes of slop and it should fail to find a status line.
277TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
278 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35279 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42280 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27281 };
282 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42283 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25284 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
285 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27286}
287
288// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
289TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
290 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35291 MockRead("\n"),
292 MockRead("\n"),
293 MockRead("Q"),
294 MockRead("J"),
295 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42296 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27297 };
298 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42299 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27300 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
301 EXPECT_EQ("DATA", out.response_data);
302}
303
304// Close the connection before enough bytes to have a status line.
305TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
306 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35307 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42308 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27309 };
310 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42311 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27312 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
313 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52314}
315
[email protected]f9d44aa2008-09-23 23:57:17316// Simulate a 204 response, lacking a Content-Length header, sent over a
317// persistent connection. The response should still terminate since a 204
318// cannot have a response body.
319TEST_F(HttpNetworkTransactionTest, StopsReading204) {
320 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35321 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
322 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42323 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17324 };
325 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42326 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17327 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
328 EXPECT_EQ("", out.response_data);
329}
330
[email protected]0877e3d2009-10-17 22:29:57331// A simple request using chunked encoding with some extra data after.
332// (Like might be seen in a pipelined response.)
333TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
334 MockRead data_reads[] = {
335 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
336 MockRead("5\r\nHello\r\n"),
337 MockRead("1\r\n"),
338 MockRead(" \r\n"),
339 MockRead("5\r\nworld\r\n"),
340 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
341 MockRead(false, OK),
342 };
343 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
344 EXPECT_EQ(OK, out.rv);
345 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
346 EXPECT_EQ("Hello world", out.response_data);
347}
348
[email protected]ef0faf2e72009-03-05 23:27:23349// Do a request using the HEAD method. Verify that we don't try to read the
350// message body (since HEAD has none).
351TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59352 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40353 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43354 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23355
[email protected]1c773ea12009-04-28 19:58:42356 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23357 request.method = "HEAD";
358 request.url = GURL("http://www.google.com/");
359 request.load_flags = 0;
360
361 MockWrite data_writes1[] = {
362 MockWrite("HEAD / HTTP/1.1\r\n"
363 "Host: www.google.com\r\n"
364 "Connection: keep-alive\r\n"
365 "Content-Length: 0\r\n\r\n"),
366 };
367 MockRead data_reads1[] = {
368 MockRead("HTTP/1.1 404 Not Found\r\n"),
369 MockRead("Server: Blah\r\n"),
370 MockRead("Content-Length: 1234\r\n\r\n"),
371
372 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42373 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23374 };
375
[email protected]5ecc992a42009-11-11 01:41:59376 StaticSocketDataProvider data1(data_reads1, data_writes1);
377 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23378
379 TestCompletionCallback callback1;
380
[email protected]684970b2009-08-14 04:54:46381 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42382 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23383
384 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42385 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23386
[email protected]1c773ea12009-04-28 19:58:42387 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23388 EXPECT_FALSE(response == NULL);
389
390 // Check that the headers got parsed.
391 EXPECT_TRUE(response->headers != NULL);
392 EXPECT_EQ(1234, response->headers->GetContentLength());
393 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
394
395 std::string server_header;
396 void* iter = NULL;
397 bool has_server_header = response->headers->EnumerateHeader(
398 &iter, "Server", &server_header);
399 EXPECT_TRUE(has_server_header);
400 EXPECT_EQ("Blah", server_header);
401
402 // Reading should give EOF right away, since there is no message body
403 // (despite non-zero content-length).
404 std::string response_data;
405 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42406 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23407 EXPECT_EQ("", response_data);
408}
409
initial.commit586acc5fe2008-07-26 22:42:52410TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59411 SessionDependencies session_deps;
412 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52413
414 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35415 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
416 MockRead("hello"),
417 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
418 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42419 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52420 };
[email protected]5ecc992a42009-11-11 01:41:59421 StaticSocketDataProvider data(data_reads, NULL);
422 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52423
424 const char* kExpectedResponseData[] = {
425 "hello", "world"
426 };
427
428 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43429 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52430
[email protected]1c773ea12009-04-28 19:58:42431 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52432 request.method = "GET";
433 request.url = GURL("http://www.google.com/");
434 request.load_flags = 0;
435
436 TestCompletionCallback callback;
437
[email protected]684970b2009-08-14 04:54:46438 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42439 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52440
441 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42442 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52443
[email protected]1c773ea12009-04-28 19:58:42444 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52445 EXPECT_TRUE(response != NULL);
446
447 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25448 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52449
450 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57451 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42452 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25453 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52454 }
455}
456
457TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59458 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40459 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43460 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52461
[email protected]1c773ea12009-04-28 19:58:42462 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52463 request.method = "POST";
464 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42465 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52466 request.upload_data->AppendBytes("foo", 3);
467 request.load_flags = 0;
468
469 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35470 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
471 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
472 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42473 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52474 };
[email protected]5ecc992a42009-11-11 01:41:59475 StaticSocketDataProvider data(data_reads, NULL);
476 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52477
478 TestCompletionCallback callback;
479
[email protected]684970b2009-08-14 04:54:46480 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42481 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52482
483 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42484 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52485
[email protected]1c773ea12009-04-28 19:58:42486 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52487 EXPECT_TRUE(response != NULL);
488
489 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25490 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52491
492 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57493 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42494 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25495 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52496}
497
[email protected]3a2d3662009-03-27 03:49:14498// This test is almost the same as Ignores100 above, but the response contains
499// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57500// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14501TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59502 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40503 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43504 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14505
[email protected]1c773ea12009-04-28 19:58:42506 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14507 request.method = "GET";
508 request.url = GURL("http://www.foo.com/");
509 request.load_flags = 0;
510
511 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57512 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
513 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14514 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42515 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14516 };
[email protected]5ecc992a42009-11-11 01:41:59517 StaticSocketDataProvider data(data_reads, NULL);
518 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14519
520 TestCompletionCallback callback;
521
[email protected]684970b2009-08-14 04:54:46522 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42523 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14524
525 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42526 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14527
[email protected]1c773ea12009-04-28 19:58:42528 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14529 EXPECT_TRUE(response != NULL);
530
531 EXPECT_TRUE(response->headers != NULL);
532 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
533
534 std::string response_data;
535 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42536 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14537 EXPECT_EQ("hello world", response_data);
538}
539
[email protected]3d2a59b2008-09-26 19:44:25540// read_failure specifies a read failure that should cause the network
541// transaction to resend the request.
542void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
543 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59544 SessionDependencies session_deps;
545 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52546
[email protected]1c773ea12009-04-28 19:58:42547 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52548 request.method = "GET";
549 request.url = GURL("http://www.foo.com/");
550 request.load_flags = 0;
551
552 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35553 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
554 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25555 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52556 };
[email protected]5ecc992a42009-11-11 01:41:59557 StaticSocketDataProvider data1(data1_reads, NULL);
558 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52559
560 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35561 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
562 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42563 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52564 };
[email protected]5ecc992a42009-11-11 01:41:59565 StaticSocketDataProvider data2(data2_reads, NULL);
566 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52567
568 const char* kExpectedResponseData[] = {
569 "hello", "world"
570 };
571
572 for (int i = 0; i < 2; ++i) {
573 TestCompletionCallback callback;
574
[email protected]5695b8c2009-09-30 21:36:43575 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52576
[email protected]684970b2009-08-14 04:54:46577 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42578 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52579
580 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42581 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52582
[email protected]1c773ea12009-04-28 19:58:42583 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52584 EXPECT_TRUE(response != NULL);
585
586 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25587 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52588
589 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57590 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42591 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25592 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52593 }
594}
[email protected]3d2a59b2008-09-26 19:44:25595
596TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42597 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25598 KeepAliveConnectionResendRequestTest(read_failure);
599}
600
601TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42602 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25603 KeepAliveConnectionResendRequestTest(read_failure);
604}
605
606TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59607 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40608 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43609 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25610
[email protected]1c773ea12009-04-28 19:58:42611 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25612 request.method = "GET";
613 request.url = GURL("http://www.google.com/");
614 request.load_flags = 0;
615
616 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42617 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35618 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
619 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42620 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25621 };
[email protected]5ecc992a42009-11-11 01:41:59622 StaticSocketDataProvider data(data_reads, NULL);
623 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25624
625 TestCompletionCallback callback;
626
[email protected]684970b2009-08-14 04:54:46627 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42628 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25629
630 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42631 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25632
[email protected]1c773ea12009-04-28 19:58:42633 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25634 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25635}
636
637// What do various browsers do when the server closes a non-keepalive
638// connection without sending any response header or body?
639//
640// IE7: error page
641// Safari 3.1.2 (Windows): error page
642// Firefox 3.0.1: blank page
643// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42644// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
645// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25646TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
647 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42648 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35649 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
650 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42651 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25652 };
653 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42654 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25655}
[email protected]038e9a32008-10-08 22:40:16656
657// Test the request-challenge-retry sequence for basic auth.
658// (basic auth is the easiest to mock, because it has no randomness).
659TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59660 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40661 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43662 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16663
[email protected]1c773ea12009-04-28 19:58:42664 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16665 request.method = "GET";
666 request.url = GURL("http://www.google.com/");
667 request.load_flags = 0;
668
[email protected]f9ee6b52008-11-08 06:46:23669 MockWrite data_writes1[] = {
670 MockWrite("GET / HTTP/1.1\r\n"
671 "Host: www.google.com\r\n"
672 "Connection: keep-alive\r\n\r\n"),
673 };
674
[email protected]038e9a32008-10-08 22:40:16675 MockRead data_reads1[] = {
676 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
677 // Give a couple authenticate options (only the middle one is actually
678 // supported).
[email protected]22927ad2009-09-21 19:56:19679 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16680 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
681 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
682 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
683 // Large content-length -- won't matter, as connection will be reset.
684 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42685 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16686 };
687
688 // After calling trans->RestartWithAuth(), this is the request we should
689 // be issuing -- the final header line contains the credentials.
690 MockWrite data_writes2[] = {
691 MockWrite("GET / HTTP/1.1\r\n"
692 "Host: www.google.com\r\n"
693 "Connection: keep-alive\r\n"
694 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
695 };
696
697 // Lastly, the server responds with the actual content.
698 MockRead data_reads2[] = {
699 MockRead("HTTP/1.0 200 OK\r\n"),
700 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
701 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42702 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16703 };
704
[email protected]5ecc992a42009-11-11 01:41:59705 StaticSocketDataProvider data1(data_reads1, data_writes1);
706 StaticSocketDataProvider data2(data_reads2, data_writes2);
707 session_deps.socket_factory.AddSocketDataProvider(&data1);
708 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16709
710 TestCompletionCallback callback1;
711
[email protected]684970b2009-08-14 04:54:46712 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42713 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16714
715 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42716 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16717
[email protected]1c773ea12009-04-28 19:58:42718 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16719 EXPECT_FALSE(response == NULL);
720
721 // The password prompt info should have been set in response->auth_challenge.
722 EXPECT_FALSE(response->auth_challenge.get() == NULL);
723
[email protected]71e4573a2009-05-21 22:03:00724 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16725 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
726 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
727
728 TestCompletionCallback callback2;
729
730 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42731 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16732
733 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42734 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16735
736 response = trans->GetResponseInfo();
737 EXPECT_FALSE(response == NULL);
738 EXPECT_TRUE(response->auth_challenge.get() == NULL);
739 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16740}
741
[email protected]861fcd52009-08-26 02:33:46742TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
743 SessionDependencies session_deps;
744 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43745 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46746
747 HttpRequestInfo request;
748 request.method = "GET";
749 request.url = GURL("http://www.google.com/");
750 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
751
752 MockWrite data_writes[] = {
753 MockWrite("GET / HTTP/1.1\r\n"
754 "Host: www.google.com\r\n"
755 "Connection: keep-alive\r\n\r\n"),
756 };
757
758 MockRead data_reads[] = {
759 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
760 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
761 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
762 // Large content-length -- won't matter, as connection will be reset.
763 MockRead("Content-Length: 10000\r\n\r\n"),
764 MockRead(false, ERR_FAILED),
765 };
766
[email protected]5ecc992a42009-11-11 01:41:59767 StaticSocketDataProvider data(data_reads, data_writes);
768 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46769 TestCompletionCallback callback;
770
771 int rv = trans->Start(&request, &callback, NULL);
772 EXPECT_EQ(ERR_IO_PENDING, rv);
773
774 rv = callback.WaitForResult();
775 EXPECT_EQ(0, rv);
776
777 const HttpResponseInfo* response = trans->GetResponseInfo();
778 ASSERT_FALSE(response == NULL);
779 EXPECT_TRUE(response->auth_challenge.get() == NULL);
780}
781
[email protected]2d2697f92009-02-18 21:00:32782// Test the request-challenge-retry sequence for basic auth, over a keep-alive
783// connection.
784TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59785 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40786 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43787 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32788
[email protected]1c773ea12009-04-28 19:58:42789 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32790 request.method = "GET";
791 request.url = GURL("http://www.google.com/");
792 request.load_flags = 0;
793
794 MockWrite data_writes1[] = {
795 MockWrite("GET / HTTP/1.1\r\n"
796 "Host: www.google.com\r\n"
797 "Connection: keep-alive\r\n\r\n"),
798
799 // After calling trans->RestartWithAuth(), this is the request we should
800 // be issuing -- the final header line contains the credentials.
801 MockWrite("GET / HTTP/1.1\r\n"
802 "Host: www.google.com\r\n"
803 "Connection: keep-alive\r\n"
804 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
805 };
806
807 MockRead data_reads1[] = {
808 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
809 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
810 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
811 MockRead("Content-Length: 14\r\n\r\n"),
812 MockRead("Unauthorized\r\n"),
813
814 // Lastly, the server responds with the actual content.
815 MockRead("HTTP/1.1 200 OK\r\n"),
816 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
817 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42818 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32819 };
820
[email protected]5ecc992a42009-11-11 01:41:59821 StaticSocketDataProvider data1(data_reads1, data_writes1);
822 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32823
824 TestCompletionCallback callback1;
825
[email protected]684970b2009-08-14 04:54:46826 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42827 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32828
829 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42830 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32831
[email protected]1c773ea12009-04-28 19:58:42832 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32833 EXPECT_FALSE(response == NULL);
834
835 // The password prompt info should have been set in response->auth_challenge.
836 EXPECT_FALSE(response->auth_challenge.get() == NULL);
837
[email protected]71e4573a2009-05-21 22:03:00838 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32839 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
840 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
841
842 TestCompletionCallback callback2;
843
844 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42845 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32846
847 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42848 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32849
850 response = trans->GetResponseInfo();
851 EXPECT_FALSE(response == NULL);
852 EXPECT_TRUE(response->auth_challenge.get() == NULL);
853 EXPECT_EQ(100, response->headers->GetContentLength());
854}
855
856// Test the request-challenge-retry sequence for basic auth, over a keep-alive
857// connection and with no response body to drain.
858TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59859 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40860 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43861 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32862
[email protected]1c773ea12009-04-28 19:58:42863 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32864 request.method = "GET";
865 request.url = GURL("http://www.google.com/");
866 request.load_flags = 0;
867
868 MockWrite data_writes1[] = {
869 MockWrite("GET / HTTP/1.1\r\n"
870 "Host: www.google.com\r\n"
871 "Connection: keep-alive\r\n\r\n"),
872
873 // After calling trans->RestartWithAuth(), this is the request we should
874 // be issuing -- the final header line contains the credentials.
875 MockWrite("GET / HTTP/1.1\r\n"
876 "Host: www.google.com\r\n"
877 "Connection: keep-alive\r\n"
878 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
879 };
880
[email protected]2d2697f92009-02-18 21:00:32881 MockRead data_reads1[] = {
882 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
883 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:31884 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:32885
886 // Lastly, the server responds with the actual content.
887 MockRead("HTTP/1.1 200 OK\r\n"),
888 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
889 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42890 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32891 };
892
[email protected]5ecc992a42009-11-11 01:41:59893 StaticSocketDataProvider data1(data_reads1, data_writes1);
894 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32895
896 TestCompletionCallback callback1;
897
[email protected]684970b2009-08-14 04:54:46898 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42899 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32900
901 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42902 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32903
[email protected]1c773ea12009-04-28 19:58:42904 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32905 EXPECT_FALSE(response == NULL);
906
907 // The password prompt info should have been set in response->auth_challenge.
908 EXPECT_FALSE(response->auth_challenge.get() == NULL);
909
[email protected]71e4573a2009-05-21 22:03:00910 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32911 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
912 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
913
914 TestCompletionCallback callback2;
915
916 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42917 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32918
919 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42920 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32921
922 response = trans->GetResponseInfo();
923 EXPECT_FALSE(response == NULL);
924 EXPECT_TRUE(response->auth_challenge.get() == NULL);
925 EXPECT_EQ(100, response->headers->GetContentLength());
926}
927
928// Test the request-challenge-retry sequence for basic auth, over a keep-alive
929// connection and with a large response body to drain.
930TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:59931 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40932 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43933 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32934
[email protected]1c773ea12009-04-28 19:58:42935 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32936 request.method = "GET";
937 request.url = GURL("http://www.google.com/");
938 request.load_flags = 0;
939
940 MockWrite data_writes1[] = {
941 MockWrite("GET / HTTP/1.1\r\n"
942 "Host: www.google.com\r\n"
943 "Connection: keep-alive\r\n\r\n"),
944
945 // After calling trans->RestartWithAuth(), this is the request we should
946 // be issuing -- the final header line contains the credentials.
947 MockWrite("GET / HTTP/1.1\r\n"
948 "Host: www.google.com\r\n"
949 "Connection: keep-alive\r\n"
950 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
951 };
952
953 // Respond with 5 kb of response body.
954 std::string large_body_string("Unauthorized");
955 large_body_string.append(5 * 1024, ' ');
956 large_body_string.append("\r\n");
957
958 MockRead data_reads1[] = {
959 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
960 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
961 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
962 // 5134 = 12 + 5 * 1024 + 2
963 MockRead("Content-Length: 5134\r\n\r\n"),
964 MockRead(true, large_body_string.data(), large_body_string.size()),
965
966 // Lastly, the server responds with the actual content.
967 MockRead("HTTP/1.1 200 OK\r\n"),
968 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
969 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42970 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32971 };
972
[email protected]5ecc992a42009-11-11 01:41:59973 StaticSocketDataProvider data1(data_reads1, data_writes1);
974 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32975
976 TestCompletionCallback callback1;
977
[email protected]684970b2009-08-14 04:54:46978 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42979 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32980
981 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42982 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32983
[email protected]1c773ea12009-04-28 19:58:42984 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32985 EXPECT_FALSE(response == NULL);
986
987 // The password prompt info should have been set in response->auth_challenge.
988 EXPECT_FALSE(response->auth_challenge.get() == NULL);
989
[email protected]71e4573a2009-05-21 22:03:00990 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32991 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
992 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
993
994 TestCompletionCallback callback2;
995
996 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42997 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32998
999 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421000 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321001
1002 response = trans->GetResponseInfo();
1003 EXPECT_FALSE(response == NULL);
1004 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1005 EXPECT_EQ(100, response->headers->GetContentLength());
1006}
1007
1008// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311009// connection, but the server gets impatient and closes the connection.
1010TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1011 SessionDependencies session_deps;
1012 scoped_ptr<HttpTransaction> trans(
1013 new HttpNetworkTransaction(CreateSession(&session_deps)));
1014
1015 HttpRequestInfo request;
1016 request.method = "GET";
1017 request.url = GURL("http://www.google.com/");
1018 request.load_flags = 0;
1019
1020 MockWrite data_writes1[] = {
1021 MockWrite("GET / HTTP/1.1\r\n"
1022 "Host: www.google.com\r\n"
1023 "Connection: keep-alive\r\n\r\n"),
1024 // This simulates the seemingly successful write to a closed connection
1025 // if the bug is not fixed.
1026 MockWrite("GET / HTTP/1.1\r\n"
1027 "Host: www.google.com\r\n"
1028 "Connection: keep-alive\r\n"
1029 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1030 };
1031
1032 MockRead data_reads1[] = {
1033 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1034 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1035 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1036 MockRead("Content-Length: 14\r\n\r\n"),
1037 // Tell MockTCPClientSocket to simulate the server closing the connection.
1038 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1039 MockRead("Unauthorized\r\n"),
1040 MockRead(false, OK), // The server closes the connection.
1041 };
1042
1043 // After calling trans->RestartWithAuth(), this is the request we should
1044 // be issuing -- the final header line contains the credentials.
1045 MockWrite data_writes2[] = {
1046 MockWrite("GET / HTTP/1.1\r\n"
1047 "Host: www.google.com\r\n"
1048 "Connection: keep-alive\r\n"
1049 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1050 };
1051
1052 // Lastly, the server responds with the actual content.
1053 MockRead data_reads2[] = {
1054 MockRead("HTTP/1.1 200 OK\r\n"),
1055 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1056 MockRead("Content-Length: 100\r\n\r\n"),
1057 MockRead(false, OK),
1058 };
1059
1060 StaticSocketDataProvider data1(data_reads1, data_writes1);
1061 StaticSocketDataProvider data2(data_reads2, data_writes2);
1062 session_deps.socket_factory.AddSocketDataProvider(&data1);
1063 session_deps.socket_factory.AddSocketDataProvider(&data2);
1064
1065 TestCompletionCallback callback1;
1066
1067 int rv = trans->Start(&request, &callback1, NULL);
1068 EXPECT_EQ(ERR_IO_PENDING, rv);
1069
1070 rv = callback1.WaitForResult();
1071 EXPECT_EQ(OK, rv);
1072
1073 const HttpResponseInfo* response = trans->GetResponseInfo();
1074 EXPECT_FALSE(response == NULL);
1075
1076 // The password prompt info should have been set in response->auth_challenge.
1077 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1078
1079 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1080 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1081 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1082
1083 TestCompletionCallback callback2;
1084
1085 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1086 EXPECT_EQ(ERR_IO_PENDING, rv);
1087
1088 rv = callback2.WaitForResult();
1089 EXPECT_EQ(OK, rv);
1090
1091 response = trans->GetResponseInfo();
1092 ASSERT_FALSE(response == NULL);
1093 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1094 EXPECT_EQ(100, response->headers->GetContentLength());
1095}
1096
1097// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321098// proxy connection, when setting up an SSL tunnel.
1099TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1100 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591101 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1102 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321103
[email protected]5695b8c2009-09-30 21:36:431104 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321105
[email protected]1c773ea12009-04-28 19:58:421106 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321107 request.method = "GET";
1108 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461109 // Ensure that proxy authentication is attempted even
1110 // when the no authentication data flag is set.
1111 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321112
1113 // Since we have proxy, should try to establish tunnel.
1114 MockWrite data_writes1[] = {
1115 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451116 "Host: www.google.com\r\n"
1117 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321118
1119 // After calling trans->RestartWithAuth(), this is the request we should
1120 // be issuing -- the final header line contains the credentials.
1121 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1122 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451123 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321124 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1125 };
1126
1127 // The proxy responds to the connect with a 407, using a persistent
1128 // connection.
1129 MockRead data_reads1[] = {
1130 // No credentials.
1131 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1132 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1133 MockRead("Content-Length: 10\r\n\r\n"),
1134 MockRead("0123456789"),
1135
1136 // Wrong credentials (wrong password).
1137 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1138 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1139 MockRead("Content-Length: 10\r\n\r\n"),
1140 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421141 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321142 };
1143
[email protected]5ecc992a42009-11-11 01:41:591144 StaticSocketDataProvider data1(data_reads1, data_writes1);
1145 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321146
1147 TestCompletionCallback callback1;
1148
[email protected]684970b2009-08-14 04:54:461149 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421150 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321151
1152 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421153 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321154
[email protected]1c773ea12009-04-28 19:58:421155 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321156 EXPECT_FALSE(response == NULL);
1157
1158 EXPECT_TRUE(response->headers->IsKeepAlive());
1159 EXPECT_EQ(407, response->headers->response_code());
1160 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421161 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321162
1163 // The password prompt info should have been set in response->auth_challenge.
1164 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1165
[email protected]71e4573a2009-05-21 22:03:001166 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321167 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1168 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1169
1170 TestCompletionCallback callback2;
1171
1172 // Wrong password (should be "bar").
1173 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421174 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321175
1176 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421177 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321178
1179 response = trans->GetResponseInfo();
1180 EXPECT_FALSE(response == NULL);
1181
1182 EXPECT_TRUE(response->headers->IsKeepAlive());
1183 EXPECT_EQ(407, response->headers->response_code());
1184 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421185 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321186
1187 // The password prompt info should have been set in response->auth_challenge.
1188 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1189
[email protected]71e4573a2009-05-21 22:03:001190 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321191 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1192 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1193}
1194
[email protected]a8e9b162009-03-12 00:06:441195// Test that we don't read the response body when we fail to establish a tunnel,
1196// even if the user cancels the proxy's auth attempt.
1197TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1198 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591199 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441200
[email protected]e44de5d2009-06-05 20:12:451201 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441202
[email protected]5695b8c2009-09-30 21:36:431203 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441204
[email protected]1c773ea12009-04-28 19:58:421205 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441206 request.method = "GET";
1207 request.url = GURL("https://www.google.com/");
1208 request.load_flags = 0;
1209
1210 // Since we have proxy, should try to establish tunnel.
1211 MockWrite data_writes[] = {
1212 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451213 "Host: www.google.com\r\n"
1214 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441215 };
1216
1217 // The proxy responds to the connect with a 407.
1218 MockRead data_reads[] = {
1219 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1220 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1221 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421222 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441223 };
1224
[email protected]5ecc992a42009-11-11 01:41:591225 StaticSocketDataProvider data(data_reads, data_writes);
1226 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441227
1228 TestCompletionCallback callback;
1229
[email protected]684970b2009-08-14 04:54:461230 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421231 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441232
1233 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421234 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441235
[email protected]1c773ea12009-04-28 19:58:421236 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441237 EXPECT_FALSE(response == NULL);
1238
1239 EXPECT_TRUE(response->headers->IsKeepAlive());
1240 EXPECT_EQ(407, response->headers->response_code());
1241 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421242 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441243
1244 std::string response_data;
1245 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421246 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441247}
1248
[email protected]ff007e162009-05-23 09:13:151249void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081250 const MockRead& status, int expected_status) {
1251 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591252 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081253
[email protected]228ff742009-06-05 01:19:591254 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081255
[email protected]5695b8c2009-09-30 21:36:431256 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081257
[email protected]1c773ea12009-04-28 19:58:421258 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081259 request.method = "GET";
1260 request.url = GURL("https://www.google.com/");
1261 request.load_flags = 0;
1262
1263 // Since we have proxy, should try to establish tunnel.
1264 MockWrite data_writes[] = {
1265 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451266 "Host: www.google.com\r\n"
1267 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081268 };
1269
1270 MockRead data_reads[] = {
1271 status,
1272 MockRead("Content-Length: 10\r\n\r\n"),
1273 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421274 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081275 };
1276
[email protected]5ecc992a42009-11-11 01:41:591277 StaticSocketDataProvider data(data_reads, data_writes);
1278 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081279
1280 TestCompletionCallback callback;
1281
[email protected]684970b2009-08-14 04:54:461282 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421283 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081284
1285 rv = callback.WaitForResult();
1286 EXPECT_EQ(expected_status, rv);
1287}
1288
[email protected]ff007e162009-05-23 09:13:151289void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081290 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421291 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081292}
1293
1294TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1295 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1296}
1297
1298TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1299 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1300}
1301
1302TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1303 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1304}
1305
1306TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1307 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1308}
1309
1310TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1311 ConnectStatusHelper(
1312 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1313}
1314
1315TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1316 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1317}
1318
1319TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1320 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1321}
1322
1323TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1324 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1325}
1326
1327TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1328 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1329}
1330
1331TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1332 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1333}
1334
1335TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1336 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1337}
1338
1339TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1340 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1341}
1342
1343TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1344 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1345}
1346
1347TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1348 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1349}
1350
1351TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1352 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1353}
1354
1355TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1356 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1357}
1358
1359TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1360 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1361}
1362
1363TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1364 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1365}
1366
1367TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1368 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1369}
1370
1371TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1372 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1373}
1374
1375TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1376 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1377}
1378
1379TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1380 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1381}
1382
1383TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1384 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1385}
1386
1387TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1388 ConnectStatusHelperWithExpectedStatus(
1389 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421390 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081391}
1392
1393TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1394 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1395}
1396
1397TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1398 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1399}
1400
1401TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1402 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1403}
1404
1405TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1406 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1407}
1408
1409TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1410 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1411}
1412
1413TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1414 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1415}
1416
1417TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1418 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1419}
1420
1421TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1422 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1423}
1424
1425TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1426 ConnectStatusHelper(
1427 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1428}
1429
1430TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1431 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1432}
1433
1434TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1435 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1436}
1437
1438TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1439 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1440}
1441
1442TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1443 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1444}
1445
1446TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1447 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1448}
1449
1450TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1451 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1452}
1453
1454TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1455 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1456}
1457
[email protected]038e9a32008-10-08 22:40:161458// Test the flow when both the proxy server AND origin server require
1459// authentication. Again, this uses basic auth for both since that is
1460// the simplest to mock.
1461TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591462 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011463
[email protected]038e9a32008-10-08 22:40:161464 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421465 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431466 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161467
[email protected]1c773ea12009-04-28 19:58:421468 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161469 request.method = "GET";
1470 request.url = GURL("http://www.google.com/");
1471 request.load_flags = 0;
1472
[email protected]f9ee6b52008-11-08 06:46:231473 MockWrite data_writes1[] = {
1474 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1475 "Host: www.google.com\r\n"
1476 "Proxy-Connection: keep-alive\r\n\r\n"),
1477 };
1478
[email protected]038e9a32008-10-08 22:40:161479 MockRead data_reads1[] = {
1480 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1481 // Give a couple authenticate options (only the middle one is actually
1482 // supported).
[email protected]22927ad2009-09-21 19:56:191483 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161484 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1485 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1486 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1487 // Large content-length -- won't matter, as connection will be reset.
1488 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421489 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161490 };
1491
1492 // After calling trans->RestartWithAuth() the first time, this is the
1493 // request we should be issuing -- the final header line contains the
1494 // proxy's credentials.
1495 MockWrite data_writes2[] = {
1496 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1497 "Host: www.google.com\r\n"
1498 "Proxy-Connection: keep-alive\r\n"
1499 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1500 };
1501
1502 // Now the proxy server lets the request pass through to origin server.
1503 // The origin server responds with a 401.
1504 MockRead data_reads2[] = {
1505 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1506 // Note: We are using the same realm-name as the proxy server. This is
1507 // completely valid, as realms are unique across hosts.
1508 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1509 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1510 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421511 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161512 };
1513
1514 // After calling trans->RestartWithAuth() the second time, we should send
1515 // the credentials for both the proxy and origin server.
1516 MockWrite data_writes3[] = {
1517 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1518 "Host: www.google.com\r\n"
1519 "Proxy-Connection: keep-alive\r\n"
1520 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1521 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1522 };
1523
1524 // Lastly we get the desired content.
1525 MockRead data_reads3[] = {
1526 MockRead("HTTP/1.0 200 OK\r\n"),
1527 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1528 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421529 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161530 };
1531
[email protected]5ecc992a42009-11-11 01:41:591532 StaticSocketDataProvider data1(data_reads1, data_writes1);
1533 StaticSocketDataProvider data2(data_reads2, data_writes2);
1534 StaticSocketDataProvider data3(data_reads3, data_writes3);
1535 session_deps.socket_factory.AddSocketDataProvider(&data1);
1536 session_deps.socket_factory.AddSocketDataProvider(&data2);
1537 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161538
1539 TestCompletionCallback callback1;
1540
[email protected]684970b2009-08-14 04:54:461541 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421542 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161543
1544 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421545 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161546
[email protected]1c773ea12009-04-28 19:58:421547 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161548 EXPECT_FALSE(response == NULL);
1549
1550 // The password prompt info should have been set in response->auth_challenge.
1551 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1552
[email protected]71e4573a2009-05-21 22:03:001553 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161554 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1555 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1556
1557 TestCompletionCallback callback2;
1558
1559 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421560 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161561
1562 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421563 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161564
1565 response = trans->GetResponseInfo();
1566 EXPECT_FALSE(response == NULL);
1567 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1568
[email protected]71e4573a2009-05-21 22:03:001569 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161570 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1571 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1572
1573 TestCompletionCallback callback3;
1574
1575 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421576 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161577
1578 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421579 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161580
1581 response = trans->GetResponseInfo();
1582 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1583 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161584}
[email protected]4ddaf2502008-10-23 18:26:191585
[email protected]ea9dc9a2009-09-05 00:43:321586// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1587// can't hook into its internals to cause it to generate predictable NTLM
1588// authorization headers.
1589#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291590// The NTLM authentication unit tests were generated by capturing the HTTP
1591// requests and responses using Fiddler 2 and inspecting the generated random
1592// bytes in the debugger.
1593
1594// Enter the correct password and authenticate successfully.
1595TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421596 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201597 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591598 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401599 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431600 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241601
[email protected]1c773ea12009-04-28 19:58:421602 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241603 request.method = "GET";
1604 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1605 request.load_flags = 0;
1606
1607 MockWrite data_writes1[] = {
1608 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1609 "Host: 172.22.68.17\r\n"
1610 "Connection: keep-alive\r\n\r\n"),
1611 };
1612
1613 MockRead data_reads1[] = {
1614 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1615 // Negotiate and NTLM are often requested together. We only support NTLM.
1616 MockRead("WWW-Authenticate: Negotiate\r\n"),
1617 MockRead("WWW-Authenticate: NTLM\r\n"),
1618 MockRead("Connection: close\r\n"),
1619 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361620 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241621 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421622 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241623 };
1624
1625 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221626 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241627 // request we should be issuing -- the final header line contains a Type
1628 // 1 message.
1629 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1630 "Host: 172.22.68.17\r\n"
1631 "Connection: keep-alive\r\n"
1632 "Authorization: NTLM "
1633 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1634
1635 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1636 // (the credentials for the origin server). The second request continues
1637 // on the same connection.
1638 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1639 "Host: 172.22.68.17\r\n"
1640 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291641 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1642 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1643 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1644 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1645 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241646 };
1647
1648 MockRead data_reads2[] = {
1649 // The origin server responds with a Type 2 message.
1650 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1651 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291652 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241653 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1654 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1655 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1656 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1657 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1658 "BtAAAAAAA=\r\n"),
1659 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361660 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241661 MockRead("You are not authorized to view this page\r\n"),
1662
1663 // Lastly we get the desired content.
1664 MockRead("HTTP/1.1 200 OK\r\n"),
1665 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1666 MockRead("Content-Length: 13\r\n\r\n"),
1667 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421668 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241669 };
1670
[email protected]5ecc992a42009-11-11 01:41:591671 StaticSocketDataProvider data1(data_reads1, data_writes1);
1672 StaticSocketDataProvider data2(data_reads2, data_writes2);
1673 session_deps.socket_factory.AddSocketDataProvider(&data1);
1674 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241675
1676 TestCompletionCallback callback1;
1677
[email protected]684970b2009-08-14 04:54:461678 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421679 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241680
1681 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421682 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241683
[email protected]0757e7702009-03-27 04:00:221684 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1685 TestCompletionCallback callback2;
1686 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421687 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221688 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421689 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221690 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1691
[email protected]1c773ea12009-04-28 19:58:421692 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241693 EXPECT_FALSE(response == NULL);
1694
1695 // The password prompt info should have been set in response->auth_challenge.
1696 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1697
[email protected]71e4573a2009-05-21 22:03:001698 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241699 EXPECT_EQ(L"", response->auth_challenge->realm);
1700 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1701
[email protected]0757e7702009-03-27 04:00:221702 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241703
[email protected]0757e7702009-03-27 04:00:221704 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421705 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241706
[email protected]0757e7702009-03-27 04:00:221707 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421708 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241709
1710 response = trans->GetResponseInfo();
1711 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1712 EXPECT_EQ(13, response->headers->GetContentLength());
1713}
1714
[email protected]385a4672009-03-11 22:21:291715// Enter a wrong password, and then the correct one.
1716TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421717 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201718 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591719 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401720 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431721 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291722
[email protected]1c773ea12009-04-28 19:58:421723 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291724 request.method = "GET";
1725 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1726 request.load_flags = 0;
1727
1728 MockWrite data_writes1[] = {
1729 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1730 "Host: 172.22.68.17\r\n"
1731 "Connection: keep-alive\r\n\r\n"),
1732 };
1733
1734 MockRead data_reads1[] = {
1735 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1736 // Negotiate and NTLM are often requested together. We only support NTLM.
1737 MockRead("WWW-Authenticate: Negotiate\r\n"),
1738 MockRead("WWW-Authenticate: NTLM\r\n"),
1739 MockRead("Connection: close\r\n"),
1740 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361741 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291742 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421743 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291744 };
1745
1746 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221747 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291748 // request we should be issuing -- the final header line contains a Type
1749 // 1 message.
1750 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1751 "Host: 172.22.68.17\r\n"
1752 "Connection: keep-alive\r\n"
1753 "Authorization: NTLM "
1754 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1755
1756 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1757 // (the credentials for the origin server). The second request continues
1758 // on the same connection.
1759 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1760 "Host: 172.22.68.17\r\n"
1761 "Connection: keep-alive\r\n"
1762 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1763 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1764 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1765 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1766 "4Ww7b7E=\r\n\r\n"),
1767 };
1768
1769 MockRead data_reads2[] = {
1770 // The origin server responds with a Type 2 message.
1771 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1772 MockRead("WWW-Authenticate: NTLM "
1773 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1774 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1775 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1776 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1777 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1778 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1779 "BtAAAAAAA=\r\n"),
1780 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361781 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291782 MockRead("You are not authorized to view this page\r\n"),
1783
1784 // Wrong password.
1785 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1786 MockRead("WWW-Authenticate: Negotiate\r\n"),
1787 MockRead("WWW-Authenticate: NTLM\r\n"),
1788 MockRead("Connection: close\r\n"),
1789 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361790 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291791 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421792 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291793 };
1794
1795 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221796 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291797 // request we should be issuing -- the final header line contains a Type
1798 // 1 message.
1799 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1800 "Host: 172.22.68.17\r\n"
1801 "Connection: keep-alive\r\n"
1802 "Authorization: NTLM "
1803 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1804
1805 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1806 // (the credentials for the origin server). The second request continues
1807 // on the same connection.
1808 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1809 "Host: 172.22.68.17\r\n"
1810 "Connection: keep-alive\r\n"
1811 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1812 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1813 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1814 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1815 "+4MUm7c=\r\n\r\n"),
1816 };
1817
1818 MockRead data_reads3[] = {
1819 // The origin server responds with a Type 2 message.
1820 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1821 MockRead("WWW-Authenticate: NTLM "
1822 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1823 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1824 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1825 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1826 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1827 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1828 "BtAAAAAAA=\r\n"),
1829 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361830 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291831 MockRead("You are not authorized to view this page\r\n"),
1832
1833 // Lastly we get the desired content.
1834 MockRead("HTTP/1.1 200 OK\r\n"),
1835 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1836 MockRead("Content-Length: 13\r\n\r\n"),
1837 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421838 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291839 };
1840
[email protected]5ecc992a42009-11-11 01:41:591841 StaticSocketDataProvider data1(data_reads1, data_writes1);
1842 StaticSocketDataProvider data2(data_reads2, data_writes2);
1843 StaticSocketDataProvider data3(data_reads3, data_writes3);
1844 session_deps.socket_factory.AddSocketDataProvider(&data1);
1845 session_deps.socket_factory.AddSocketDataProvider(&data2);
1846 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:291847
1848 TestCompletionCallback callback1;
1849
[email protected]684970b2009-08-14 04:54:461850 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421851 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291852
1853 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421854 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291855
[email protected]0757e7702009-03-27 04:00:221856 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291857 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221858 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421859 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291860 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421861 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221862 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291863
[email protected]1c773ea12009-04-28 19:58:421864 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291865 EXPECT_FALSE(response == NULL);
1866
1867 // The password prompt info should have been set in response->auth_challenge.
1868 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1869
[email protected]71e4573a2009-05-21 22:03:001870 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291871 EXPECT_EQ(L"", response->auth_challenge->realm);
1872 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1873
1874 TestCompletionCallback callback3;
1875
[email protected]0757e7702009-03-27 04:00:221876 // Enter the wrong password.
1877 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421878 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291879
1880 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421881 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291882
[email protected]0757e7702009-03-27 04:00:221883 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1884 TestCompletionCallback callback4;
1885 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421886 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221887 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421888 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221889 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1890
1891 response = trans->GetResponseInfo();
1892 EXPECT_FALSE(response == NULL);
1893
1894 // The password prompt info should have been set in response->auth_challenge.
1895 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1896
[email protected]71e4573a2009-05-21 22:03:001897 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221898 EXPECT_EQ(L"", response->auth_challenge->realm);
1899 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1900
1901 TestCompletionCallback callback5;
1902
1903 // Now enter the right password.
1904 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:421905 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221906
1907 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421908 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221909
[email protected]385a4672009-03-11 22:21:291910 response = trans->GetResponseInfo();
1911 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1912 EXPECT_EQ(13, response->headers->GetContentLength());
1913}
[email protected]ea9dc9a2009-09-05 00:43:321914#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:291915
[email protected]4ddaf2502008-10-23 18:26:191916// Test reading a server response which has only headers, and no body.
1917// After some maximum number of bytes is consumed, the transaction should
1918// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
1919TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:591920 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401921 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431922 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:191923
[email protected]1c773ea12009-04-28 19:58:421924 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:191925 request.method = "GET";
1926 request.url = GURL("http://www.google.com/");
1927 request.load_flags = 0;
1928
[email protected]b75b7b2f2009-10-06 00:54:531929 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:431930 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:531931 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:191932
1933 MockRead data_reads[] = {
1934 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:431935 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:191936 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:421937 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:191938 };
[email protected]5ecc992a42009-11-11 01:41:591939 StaticSocketDataProvider data(data_reads, NULL);
1940 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:191941
1942 TestCompletionCallback callback;
1943
[email protected]684970b2009-08-14 04:54:461944 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421945 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:191946
1947 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421948 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:191949
[email protected]1c773ea12009-04-28 19:58:421950 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:191951 EXPECT_TRUE(response == NULL);
1952}
[email protected]f4e426b2008-11-05 00:24:491953
1954// Make sure that we don't try to reuse a TCPClientSocket when failing to
1955// establish tunnel.
1956// http://code.google.com/p/chromium/issues/detail?id=3772
1957TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
1958 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591959 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011960
[email protected]228ff742009-06-05 01:19:591961 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:491962
[email protected]5695b8c2009-09-30 21:36:431963 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:491964
[email protected]1c773ea12009-04-28 19:58:421965 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:491966 request.method = "GET";
1967 request.url = GURL("https://www.google.com/");
1968 request.load_flags = 0;
1969
1970 // Since we have proxy, should try to establish tunnel.
1971 MockWrite data_writes1[] = {
1972 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451973 "Host: www.google.com\r\n"
1974 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:491975 };
1976
[email protected]77848d12008-11-14 00:00:221977 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:491978 // connection. Usually a proxy would return 501 (not implemented),
1979 // or 200 (tunnel established).
1980 MockRead data_reads1[] = {
1981 MockRead("HTTP/1.1 404 Not Found\r\n"),
1982 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421983 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:491984 };
1985
[email protected]5ecc992a42009-11-11 01:41:591986 StaticSocketDataProvider data1(data_reads1, data_writes1);
1987 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:491988
1989 TestCompletionCallback callback1;
1990
[email protected]684970b2009-08-14 04:54:461991 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421992 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:491993
1994 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421995 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:491996
[email protected]1c773ea12009-04-28 19:58:421997 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:081998 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:491999
[email protected]b4404c02009-04-10 16:38:522000 // Empty the current queue. This is necessary because idle sockets are
2001 // added to the connection pool asynchronously with a PostTask.
2002 MessageLoop::current()->RunAllPending();
2003
[email protected]f4e426b2008-11-05 00:24:492004 // We now check to make sure the TCPClientSocket was not added back to
2005 // the pool.
[email protected]a937a06d2009-08-19 21:19:242006 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492007 trans.reset();
[email protected]b4404c02009-04-10 16:38:522008 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492009 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242010 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492011}
[email protected]372d34a2008-11-05 21:30:512012
[email protected]1b157c02009-04-21 01:55:402013// Make sure that we recycle a socket after reading all of the response body.
2014TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592015 SessionDependencies session_deps;
2016 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402017
[email protected]5695b8c2009-09-30 21:36:432018 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402019
[email protected]1c773ea12009-04-28 19:58:422020 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402021 request.method = "GET";
2022 request.url = GURL("http://www.google.com/");
2023 request.load_flags = 0;
2024
2025 MockRead data_reads[] = {
2026 // A part of the response body is received with the response headers.
2027 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2028 // The rest of the response body is received in two parts.
2029 MockRead("lo"),
2030 MockRead(" world"),
2031 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422032 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402033 };
2034
[email protected]5ecc992a42009-11-11 01:41:592035 StaticSocketDataProvider data(data_reads, NULL);
2036 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402037
2038 TestCompletionCallback callback;
2039
[email protected]684970b2009-08-14 04:54:462040 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422041 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402042
2043 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422044 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402045
[email protected]1c773ea12009-04-28 19:58:422046 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402047 EXPECT_TRUE(response != NULL);
2048
2049 EXPECT_TRUE(response->headers != NULL);
2050 std::string status_line = response->headers->GetStatusLine();
2051 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2052
[email protected]a937a06d2009-08-19 21:19:242053 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402054
2055 std::string response_data;
2056 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422057 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402058 EXPECT_EQ("hello world", response_data);
2059
2060 // Empty the current queue. This is necessary because idle sockets are
2061 // added to the connection pool asynchronously with a PostTask.
2062 MessageLoop::current()->RunAllPending();
2063
2064 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242065 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402066}
2067
[email protected]b4404c02009-04-10 16:38:522068// Make sure that we recycle a socket after a zero-length response.
2069// http://crbug.com/9880
2070TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592071 SessionDependencies session_deps;
2072 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522073
[email protected]5695b8c2009-09-30 21:36:432074 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522075
[email protected]1c773ea12009-04-28 19:58:422076 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522077 request.method = "GET";
2078 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2079 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2080 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2081 "rt=prt.2642,ol.2649,xjs.2951");
2082 request.load_flags = 0;
2083
2084 MockRead data_reads[] = {
2085 MockRead("HTTP/1.1 204 No Content\r\n"
2086 "Content-Length: 0\r\n"
2087 "Content-Type: text/html\r\n\r\n"),
2088 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422089 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522090 };
2091
[email protected]5ecc992a42009-11-11 01:41:592092 StaticSocketDataProvider data(data_reads, NULL);
2093 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522094
2095 TestCompletionCallback callback;
2096
[email protected]684970b2009-08-14 04:54:462097 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422098 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522099
2100 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422101 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522102
[email protected]1c773ea12009-04-28 19:58:422103 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522104 EXPECT_TRUE(response != NULL);
2105
2106 EXPECT_TRUE(response->headers != NULL);
2107 std::string status_line = response->headers->GetStatusLine();
2108 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2109
[email protected]a937a06d2009-08-19 21:19:242110 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522111
2112 std::string response_data;
2113 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422114 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522115 EXPECT_EQ("", response_data);
2116
2117 // Empty the current queue. This is necessary because idle sockets are
2118 // added to the connection pool asynchronously with a PostTask.
2119 MessageLoop::current()->RunAllPending();
2120
2121 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242122 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522123}
2124
[email protected]372d34a2008-11-05 21:30:512125TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422126 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512127 // Transaction 1: a GET request that succeeds. The socket is recycled
2128 // after use.
2129 request[0].method = "GET";
2130 request[0].url = GURL("http://www.google.com/");
2131 request[0].load_flags = 0;
2132 // Transaction 2: a POST request. Reuses the socket kept alive from
2133 // transaction 1. The first attempts fails when writing the POST data.
2134 // This causes the transaction to retry with a new socket. The second
2135 // attempt succeeds.
2136 request[1].method = "POST";
2137 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422138 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512139 request[1].upload_data->AppendBytes("foo", 3);
2140 request[1].load_flags = 0;
2141
[email protected]228ff742009-06-05 01:19:592142 SessionDependencies session_deps;
2143 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512144
2145 // The first socket is used for transaction 1 and the first attempt of
2146 // transaction 2.
2147
2148 // The response of transaction 1.
2149 MockRead data_reads1[] = {
2150 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2151 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422152 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512153 };
2154 // The mock write results of transaction 1 and the first attempt of
2155 // transaction 2.
2156 MockWrite data_writes1[] = {
2157 MockWrite(false, 64), // GET
2158 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422159 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512160 };
[email protected]5ecc992a42009-11-11 01:41:592161 StaticSocketDataProvider data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:512162
2163 // The second socket is used for the second attempt of transaction 2.
2164
2165 // The response of transaction 2.
2166 MockRead data_reads2[] = {
2167 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2168 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422169 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512170 };
2171 // The mock write results of the second attempt of transaction 2.
2172 MockWrite data_writes2[] = {
2173 MockWrite(false, 93), // POST
2174 MockWrite(false, 3), // POST data
2175 };
[email protected]5ecc992a42009-11-11 01:41:592176 StaticSocketDataProvider data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:512177
[email protected]5ecc992a42009-11-11 01:41:592178 session_deps.socket_factory.AddSocketDataProvider(&data1);
2179 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512180
2181 const char* kExpectedResponseData[] = {
2182 "hello world", "welcome"
2183 };
2184
2185 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422186 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432187 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512188
2189 TestCompletionCallback callback;
2190
[email protected]684970b2009-08-14 04:54:462191 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422192 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512193
2194 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422195 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512196
[email protected]1c773ea12009-04-28 19:58:422197 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512198 EXPECT_TRUE(response != NULL);
2199
2200 EXPECT_TRUE(response->headers != NULL);
2201 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2202
2203 std::string response_data;
2204 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422205 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512206 EXPECT_EQ(kExpectedResponseData[i], response_data);
2207 }
2208}
[email protected]f9ee6b52008-11-08 06:46:232209
2210// Test the request-challenge-retry sequence for basic auth when there is
2211// an identity in the URL. The request should be sent as normal, but when
2212// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322213TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592214 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402215 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432216 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232217
[email protected]1c773ea12009-04-28 19:58:422218 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232219 request.method = "GET";
2220 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292221 request.url = GURL("http://foo:b@[email protected]/");
2222
2223 // The password contains an escaped character -- for this test to pass it
2224 // will need to be unescaped by HttpNetworkTransaction.
2225 EXPECT_EQ("b%40r", request.url.password());
2226
[email protected]ea9dc9a2009-09-05 00:43:322227 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232228
2229 MockWrite data_writes1[] = {
2230 MockWrite("GET / HTTP/1.1\r\n"
2231 "Host: www.google.com\r\n"
2232 "Connection: keep-alive\r\n\r\n"),
2233 };
2234
2235 MockRead data_reads1[] = {
2236 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2237 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2238 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422239 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232240 };
2241
2242 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322243 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232244 MockWrite data_writes2[] = {
2245 MockWrite("GET / HTTP/1.1\r\n"
2246 "Host: www.google.com\r\n"
2247 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292248 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232249 };
2250
2251 MockRead data_reads2[] = {
2252 MockRead("HTTP/1.0 200 OK\r\n"),
2253 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422254 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232255 };
2256
[email protected]5ecc992a42009-11-11 01:41:592257 StaticSocketDataProvider data1(data_reads1, data_writes1);
2258 StaticSocketDataProvider data2(data_reads2, data_writes2);
2259 session_deps.socket_factory.AddSocketDataProvider(&data1);
2260 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232261
2262 TestCompletionCallback callback1;
2263
[email protected]684970b2009-08-14 04:54:462264 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422265 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232266
2267 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422268 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232269
[email protected]0757e7702009-03-27 04:00:222270 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2271 TestCompletionCallback callback2;
2272 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422273 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222274 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422275 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222276 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2277
[email protected]1c773ea12009-04-28 19:58:422278 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232279 EXPECT_FALSE(response == NULL);
2280
2281 // There is no challenge info, since the identity in URL worked.
2282 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2283
2284 EXPECT_EQ(100, response->headers->GetContentLength());
2285
2286 // Empty the current queue.
2287 MessageLoop::current()->RunAllPending();
2288}
2289
[email protected]ea9dc9a2009-09-05 00:43:322290// Test the request-challenge-retry sequence for basic auth when there is
2291// an incorrect identity in the URL. The identity from the URL should be used
2292// only once.
2293TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2294 SessionDependencies session_deps;
2295 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432296 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322297
2298 HttpRequestInfo request;
2299 request.method = "GET";
2300 // Note: the URL has a username:password in it. The password "baz" is
2301 // wrong (should be "bar").
2302 request.url = GURL("http://foo:[email protected]/");
2303
2304 request.load_flags = LOAD_NORMAL;
2305
2306 MockWrite data_writes1[] = {
2307 MockWrite("GET / HTTP/1.1\r\n"
2308 "Host: www.google.com\r\n"
2309 "Connection: keep-alive\r\n\r\n"),
2310 };
2311
2312 MockRead data_reads1[] = {
2313 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2314 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2315 MockRead("Content-Length: 10\r\n\r\n"),
2316 MockRead(false, ERR_FAILED),
2317 };
2318
2319 // After the challenge above, the transaction will be restarted using the
2320 // identity from the url (foo, baz) to answer the challenge.
2321 MockWrite data_writes2[] = {
2322 MockWrite("GET / HTTP/1.1\r\n"
2323 "Host: www.google.com\r\n"
2324 "Connection: keep-alive\r\n"
2325 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2326 };
2327
2328 MockRead data_reads2[] = {
2329 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2330 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2331 MockRead("Content-Length: 10\r\n\r\n"),
2332 MockRead(false, ERR_FAILED),
2333 };
2334
2335 // After the challenge above, the transaction will be restarted using the
2336 // identity supplied by the user (foo, bar) to answer the challenge.
2337 MockWrite data_writes3[] = {
2338 MockWrite("GET / HTTP/1.1\r\n"
2339 "Host: www.google.com\r\n"
2340 "Connection: keep-alive\r\n"
2341 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2342 };
2343
2344 MockRead data_reads3[] = {
2345 MockRead("HTTP/1.0 200 OK\r\n"),
2346 MockRead("Content-Length: 100\r\n\r\n"),
2347 MockRead(false, OK),
2348 };
2349
[email protected]5ecc992a42009-11-11 01:41:592350 StaticSocketDataProvider data1(data_reads1, data_writes1);
2351 StaticSocketDataProvider data2(data_reads2, data_writes2);
2352 StaticSocketDataProvider data3(data_reads3, data_writes3);
2353 session_deps.socket_factory.AddSocketDataProvider(&data1);
2354 session_deps.socket_factory.AddSocketDataProvider(&data2);
2355 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322356
2357 TestCompletionCallback callback1;
2358
2359 int rv = trans->Start(&request, &callback1, NULL);
2360 EXPECT_EQ(ERR_IO_PENDING, rv);
2361
2362 rv = callback1.WaitForResult();
2363 EXPECT_EQ(OK, rv);
2364
2365 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2366 TestCompletionCallback callback2;
2367 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2368 EXPECT_EQ(ERR_IO_PENDING, rv);
2369 rv = callback2.WaitForResult();
2370 EXPECT_EQ(OK, rv);
2371 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2372
2373 const HttpResponseInfo* response = trans->GetResponseInfo();
2374 EXPECT_FALSE(response == NULL);
2375 // The password prompt info should have been set in response->auth_challenge.
2376 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2377
2378 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2379 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2380 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2381
2382 TestCompletionCallback callback3;
2383 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2384 EXPECT_EQ(ERR_IO_PENDING, rv);
2385 rv = callback3.WaitForResult();
2386 EXPECT_EQ(OK, rv);
2387 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2388
2389 response = trans->GetResponseInfo();
2390 EXPECT_FALSE(response == NULL);
2391
2392 // There is no challenge info, since the identity worked.
2393 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2394
2395 EXPECT_EQ(100, response->headers->GetContentLength());
2396
2397 // Empty the current queue.
2398 MessageLoop::current()->RunAllPending();
2399}
2400
[email protected]f9ee6b52008-11-08 06:46:232401// Test that previously tried username/passwords for a realm get re-used.
2402TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592403 SessionDependencies session_deps;
2404 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232405
2406 // Transaction 1: authenticate (foo, bar) on MyRealm1
2407 {
[email protected]5695b8c2009-09-30 21:36:432408 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232409
[email protected]1c773ea12009-04-28 19:58:422410 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232411 request.method = "GET";
2412 request.url = GURL("http://www.google.com/x/y/z");
2413 request.load_flags = 0;
2414
2415 MockWrite data_writes1[] = {
2416 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2417 "Host: www.google.com\r\n"
2418 "Connection: keep-alive\r\n\r\n"),
2419 };
2420
2421 MockRead data_reads1[] = {
2422 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2423 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2424 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422425 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232426 };
2427
2428 // Resend with authorization (username=foo, password=bar)
2429 MockWrite data_writes2[] = {
2430 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2431 "Host: www.google.com\r\n"
2432 "Connection: keep-alive\r\n"
2433 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2434 };
2435
2436 // Sever accepts the authorization.
2437 MockRead data_reads2[] = {
2438 MockRead("HTTP/1.0 200 OK\r\n"),
2439 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422440 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232441 };
2442
[email protected]5ecc992a42009-11-11 01:41:592443 StaticSocketDataProvider data1(data_reads1, data_writes1);
2444 StaticSocketDataProvider data2(data_reads2, data_writes2);
2445 session_deps.socket_factory.AddSocketDataProvider(&data1);
2446 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232447
2448 TestCompletionCallback callback1;
2449
[email protected]684970b2009-08-14 04:54:462450 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422451 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232452
2453 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422454 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232455
[email protected]1c773ea12009-04-28 19:58:422456 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232457 EXPECT_FALSE(response == NULL);
2458
2459 // The password prompt info should have been set in
2460 // response->auth_challenge.
2461 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2462
[email protected]71e4573a2009-05-21 22:03:002463 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232464 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2465 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2466
2467 TestCompletionCallback callback2;
2468
2469 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422470 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232471
2472 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422473 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232474
2475 response = trans->GetResponseInfo();
2476 EXPECT_FALSE(response == NULL);
2477 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2478 EXPECT_EQ(100, response->headers->GetContentLength());
2479 }
2480
2481 // ------------------------------------------------------------------------
2482
2483 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2484 {
[email protected]5695b8c2009-09-30 21:36:432485 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232486
[email protected]1c773ea12009-04-28 19:58:422487 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232488 request.method = "GET";
2489 // Note that Transaction 1 was at /x/y/z, so this is in the same
2490 // protection space as MyRealm1.
2491 request.url = GURL("http://www.google.com/x/y/a/b");
2492 request.load_flags = 0;
2493
2494 MockWrite data_writes1[] = {
2495 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2496 "Host: www.google.com\r\n"
2497 "Connection: keep-alive\r\n"
2498 // Send preemptive authorization for MyRealm1
2499 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2500 };
2501
2502 // The server didn't like the preemptive authorization, and
2503 // challenges us for a different realm (MyRealm2).
2504 MockRead data_reads1[] = {
2505 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2506 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2507 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422508 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232509 };
2510
2511 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2512 MockWrite data_writes2[] = {
2513 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2514 "Host: www.google.com\r\n"
2515 "Connection: keep-alive\r\n"
2516 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2517 };
2518
2519 // Sever accepts the authorization.
2520 MockRead data_reads2[] = {
2521 MockRead("HTTP/1.0 200 OK\r\n"),
2522 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422523 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232524 };
2525
[email protected]5ecc992a42009-11-11 01:41:592526 StaticSocketDataProvider data1(data_reads1, data_writes1);
2527 StaticSocketDataProvider data2(data_reads2, data_writes2);
2528 session_deps.socket_factory.AddSocketDataProvider(&data1);
2529 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232530
2531 TestCompletionCallback callback1;
2532
[email protected]684970b2009-08-14 04:54:462533 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422534 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232535
2536 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422537 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232538
[email protected]1c773ea12009-04-28 19:58:422539 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232540 EXPECT_FALSE(response == NULL);
2541
2542 // The password prompt info should have been set in
2543 // response->auth_challenge.
2544 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2545
[email protected]71e4573a2009-05-21 22:03:002546 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232547 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2548 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2549
2550 TestCompletionCallback callback2;
2551
2552 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422553 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232554
2555 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422556 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232557
2558 response = trans->GetResponseInfo();
2559 EXPECT_FALSE(response == NULL);
2560 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2561 EXPECT_EQ(100, response->headers->GetContentLength());
2562 }
2563
2564 // ------------------------------------------------------------------------
2565
2566 // Transaction 3: Resend a request in MyRealm's protection space --
2567 // succeed with preemptive authorization.
2568 {
[email protected]5695b8c2009-09-30 21:36:432569 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232570
[email protected]1c773ea12009-04-28 19:58:422571 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232572 request.method = "GET";
2573 request.url = GURL("http://www.google.com/x/y/z2");
2574 request.load_flags = 0;
2575
2576 MockWrite data_writes1[] = {
2577 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2578 "Host: www.google.com\r\n"
2579 "Connection: keep-alive\r\n"
2580 // The authorization for MyRealm1 gets sent preemptively
2581 // (since the url is in the same protection space)
2582 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2583 };
2584
2585 // Sever accepts the preemptive authorization
2586 MockRead data_reads1[] = {
2587 MockRead("HTTP/1.0 200 OK\r\n"),
2588 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422589 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232590 };
2591
[email protected]5ecc992a42009-11-11 01:41:592592 StaticSocketDataProvider data1(data_reads1, data_writes1);
2593 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232594
2595 TestCompletionCallback callback1;
2596
[email protected]684970b2009-08-14 04:54:462597 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422598 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232599
2600 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422601 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232602
[email protected]1c773ea12009-04-28 19:58:422603 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232604 EXPECT_FALSE(response == NULL);
2605
2606 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2607 EXPECT_EQ(100, response->headers->GetContentLength());
2608 }
2609
2610 // ------------------------------------------------------------------------
2611
2612 // Transaction 4: request another URL in MyRealm (however the
2613 // url is not known to belong to the protection space, so no pre-auth).
2614 {
[email protected]5695b8c2009-09-30 21:36:432615 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232616
[email protected]1c773ea12009-04-28 19:58:422617 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232618 request.method = "GET";
2619 request.url = GURL("http://www.google.com/x/1");
2620 request.load_flags = 0;
2621
2622 MockWrite data_writes1[] = {
2623 MockWrite("GET /x/1 HTTP/1.1\r\n"
2624 "Host: www.google.com\r\n"
2625 "Connection: keep-alive\r\n\r\n"),
2626 };
2627
2628 MockRead data_reads1[] = {
2629 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2630 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2631 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422632 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232633 };
2634
2635 // Resend with authorization from MyRealm's cache.
2636 MockWrite data_writes2[] = {
2637 MockWrite("GET /x/1 HTTP/1.1\r\n"
2638 "Host: www.google.com\r\n"
2639 "Connection: keep-alive\r\n"
2640 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2641 };
2642
2643 // Sever accepts the authorization.
2644 MockRead data_reads2[] = {
2645 MockRead("HTTP/1.0 200 OK\r\n"),
2646 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422647 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232648 };
2649
[email protected]5ecc992a42009-11-11 01:41:592650 StaticSocketDataProvider data1(data_reads1, data_writes1);
2651 StaticSocketDataProvider data2(data_reads2, data_writes2);
2652 session_deps.socket_factory.AddSocketDataProvider(&data1);
2653 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232654
2655 TestCompletionCallback callback1;
2656
[email protected]684970b2009-08-14 04:54:462657 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422658 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232659
2660 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422661 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232662
[email protected]0757e7702009-03-27 04:00:222663 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2664 TestCompletionCallback callback2;
2665 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422666 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222667 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422668 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222669 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2670
[email protected]1c773ea12009-04-28 19:58:422671 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232672 EXPECT_FALSE(response == NULL);
2673 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2674 EXPECT_EQ(100, response->headers->GetContentLength());
2675 }
2676
2677 // ------------------------------------------------------------------------
2678
2679 // Transaction 5: request a URL in MyRealm, but the server rejects the
2680 // cached identity. Should invalidate and re-prompt.
2681 {
[email protected]5695b8c2009-09-30 21:36:432682 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232683
[email protected]1c773ea12009-04-28 19:58:422684 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232685 request.method = "GET";
2686 request.url = GURL("http://www.google.com/p/q/t");
2687 request.load_flags = 0;
2688
2689 MockWrite data_writes1[] = {
2690 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2691 "Host: www.google.com\r\n"
2692 "Connection: keep-alive\r\n\r\n"),
2693 };
2694
2695 MockRead data_reads1[] = {
2696 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2697 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2698 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422699 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232700 };
2701
2702 // Resend with authorization from cache for MyRealm.
2703 MockWrite data_writes2[] = {
2704 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2705 "Host: www.google.com\r\n"
2706 "Connection: keep-alive\r\n"
2707 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2708 };
2709
2710 // Sever rejects the authorization.
2711 MockRead data_reads2[] = {
2712 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2713 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2714 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422715 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232716 };
2717
2718 // At this point we should prompt for new credentials for MyRealm.
2719 // Restart with username=foo3, password=foo4.
2720 MockWrite data_writes3[] = {
2721 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2722 "Host: www.google.com\r\n"
2723 "Connection: keep-alive\r\n"
2724 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2725 };
2726
2727 // Sever accepts the authorization.
2728 MockRead data_reads3[] = {
2729 MockRead("HTTP/1.0 200 OK\r\n"),
2730 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422731 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232732 };
2733
[email protected]5ecc992a42009-11-11 01:41:592734 StaticSocketDataProvider data1(data_reads1, data_writes1);
2735 StaticSocketDataProvider data2(data_reads2, data_writes2);
2736 StaticSocketDataProvider data3(data_reads3, data_writes3);
2737 session_deps.socket_factory.AddSocketDataProvider(&data1);
2738 session_deps.socket_factory.AddSocketDataProvider(&data2);
2739 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232740
2741 TestCompletionCallback callback1;
2742
[email protected]684970b2009-08-14 04:54:462743 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422744 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232745
2746 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422747 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232748
[email protected]0757e7702009-03-27 04:00:222749 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2750 TestCompletionCallback callback2;
2751 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422752 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222753 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422754 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222755 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2756
[email protected]1c773ea12009-04-28 19:58:422757 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232758 EXPECT_FALSE(response == NULL);
2759
2760 // The password prompt info should have been set in
2761 // response->auth_challenge.
2762 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2763
[email protected]71e4573a2009-05-21 22:03:002764 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232765 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2766 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2767
[email protected]0757e7702009-03-27 04:00:222768 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232769
[email protected]0757e7702009-03-27 04:00:222770 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422771 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232772
[email protected]0757e7702009-03-27 04:00:222773 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422774 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232775
2776 response = trans->GetResponseInfo();
2777 EXPECT_FALSE(response == NULL);
2778 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2779 EXPECT_EQ(100, response->headers->GetContentLength());
2780 }
2781}
[email protected]89ceba9a2009-03-21 03:46:062782
2783// Test the ResetStateForRestart() private method.
2784TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2785 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592786 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402787 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432788 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062789
2790 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062791 trans->read_buf_ = new IOBuffer(15);
2792 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572793 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062794
2795 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:142796 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:572797 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]9b6fee12009-09-29 18:13:072815 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:062816 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:572817 EXPECT_EQ(0U, trans->request_headers_.size());
2818 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2819 EXPECT_TRUE(response->headers.get() == NULL);
2820 EXPECT_EQ(false, response->was_cached);
2821 EXPECT_EQ(0, response->ssl_info.cert_status);
2822 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:062823}
2824
[email protected]bacff652009-03-31 17:50:332825// Test HTTPS connections to a site with a bad certificate
2826TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592827 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402828 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432829 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332830
2831 HttpRequestInfo request;
2832 request.method = "GET";
2833 request.url = GURL("https://www.google.com/");
2834 request.load_flags = 0;
2835
2836 MockWrite data_writes[] = {
2837 MockWrite("GET / HTTP/1.1\r\n"
2838 "Host: www.google.com\r\n"
2839 "Connection: keep-alive\r\n\r\n"),
2840 };
2841
2842 MockRead data_reads[] = {
2843 MockRead("HTTP/1.0 200 OK\r\n"),
2844 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2845 MockRead("Content-Length: 100\r\n\r\n"),
2846 MockRead(false, OK),
2847 };
2848
[email protected]5ecc992a42009-11-11 01:41:592849 StaticSocketDataProvider ssl_bad_certificate;
2850 StaticSocketDataProvider data(data_reads, data_writes);
2851 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2852 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:332853
[email protected]5ecc992a42009-11-11 01:41:592854 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2855 session_deps.socket_factory.AddSocketDataProvider(&data);
2856 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2857 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:332858
2859 TestCompletionCallback callback;
2860
[email protected]684970b2009-08-14 04:54:462861 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332862 EXPECT_EQ(ERR_IO_PENDING, rv);
2863
2864 rv = callback.WaitForResult();
2865 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2866
2867 rv = trans->RestartIgnoringLastError(&callback);
2868 EXPECT_EQ(ERR_IO_PENDING, rv);
2869
2870 rv = callback.WaitForResult();
2871 EXPECT_EQ(OK, rv);
2872
2873 const HttpResponseInfo* response = trans->GetResponseInfo();
2874
2875 EXPECT_FALSE(response == NULL);
2876 EXPECT_EQ(100, response->headers->GetContentLength());
2877}
2878
2879// Test HTTPS connections to a site with a bad certificate, going through a
2880// proxy
2881TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592882 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332883
2884 HttpRequestInfo request;
2885 request.method = "GET";
2886 request.url = GURL("https://www.google.com/");
2887 request.load_flags = 0;
2888
2889 MockWrite proxy_writes[] = {
2890 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452891 "Host: www.google.com\r\n"
2892 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332893 };
2894
2895 MockRead proxy_reads[] = {
2896 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422897 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:332898 };
2899
2900 MockWrite data_writes[] = {
2901 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452902 "Host: www.google.com\r\n"
2903 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332904 MockWrite("GET / HTTP/1.1\r\n"
2905 "Host: www.google.com\r\n"
2906 "Connection: keep-alive\r\n\r\n"),
2907 };
2908
2909 MockRead data_reads[] = {
2910 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
2911 MockRead("HTTP/1.0 200 OK\r\n"),
2912 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2913 MockRead("Content-Length: 100\r\n\r\n"),
2914 MockRead(false, OK),
2915 };
2916
[email protected]5ecc992a42009-11-11 01:41:592917 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
2918 StaticSocketDataProvider data(data_reads, data_writes);
2919 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2920 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:332921
[email protected]5ecc992a42009-11-11 01:41:592922 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2923 session_deps.socket_factory.AddSocketDataProvider(&data);
2924 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2925 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:332926
2927 TestCompletionCallback callback;
2928
2929 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:592930 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:332931
[email protected]d207a5f2009-06-04 05:28:402932 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432933 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332934
[email protected]684970b2009-08-14 04:54:462935 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332936 EXPECT_EQ(ERR_IO_PENDING, rv);
2937
2938 rv = callback.WaitForResult();
2939 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2940
2941 rv = trans->RestartIgnoringLastError(&callback);
2942 EXPECT_EQ(ERR_IO_PENDING, rv);
2943
2944 rv = callback.WaitForResult();
2945 EXPECT_EQ(OK, rv);
2946
2947 const HttpResponseInfo* response = trans->GetResponseInfo();
2948
2949 EXPECT_FALSE(response == NULL);
2950 EXPECT_EQ(100, response->headers->GetContentLength());
2951 }
2952}
2953
[email protected]1c773ea12009-04-28 19:58:422954TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:592955 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402956 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432957 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:422958
2959 HttpRequestInfo request;
2960 request.method = "GET";
2961 request.url = GURL("http://www.google.com/");
2962 request.user_agent = "Chromium Ultra Awesome X Edition";
2963
2964 MockWrite data_writes[] = {
2965 MockWrite("GET / HTTP/1.1\r\n"
2966 "Host: www.google.com\r\n"
2967 "Connection: keep-alive\r\n"
2968 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
2969 };
2970
2971 // Lastly, the server responds with the actual content.
2972 MockRead data_reads[] = {
2973 MockRead("HTTP/1.0 200 OK\r\n"),
2974 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2975 MockRead("Content-Length: 100\r\n\r\n"),
2976 MockRead(false, OK),
2977 };
2978
[email protected]5ecc992a42009-11-11 01:41:592979 StaticSocketDataProvider data(data_reads, data_writes);
2980 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:422981
2982 TestCompletionCallback callback;
2983
[email protected]684970b2009-08-14 04:54:462984 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422985 EXPECT_EQ(ERR_IO_PENDING, rv);
2986
2987 rv = callback.WaitForResult();
2988 EXPECT_EQ(OK, rv);
2989}
2990
2991TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:592992 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402993 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432994 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:422995
2996 HttpRequestInfo request;
2997 request.method = "GET";
2998 request.url = GURL("http://www.google.com/");
2999 request.load_flags = 0;
3000 request.referrer = GURL("http://the.previous.site.com/");
3001
3002 MockWrite data_writes[] = {
3003 MockWrite("GET / HTTP/1.1\r\n"
3004 "Host: www.google.com\r\n"
3005 "Connection: keep-alive\r\n"
3006 "Referer: http://the.previous.site.com/\r\n\r\n"),
3007 };
3008
3009 // Lastly, the server responds with the actual content.
3010 MockRead data_reads[] = {
3011 MockRead("HTTP/1.0 200 OK\r\n"),
3012 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3013 MockRead("Content-Length: 100\r\n\r\n"),
3014 MockRead(false, OK),
3015 };
3016
[email protected]5ecc992a42009-11-11 01:41:593017 StaticSocketDataProvider data(data_reads, data_writes);
3018 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423019
3020 TestCompletionCallback callback;
3021
[email protected]684970b2009-08-14 04:54:463022 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423023 EXPECT_EQ(ERR_IO_PENDING, rv);
3024
3025 rv = callback.WaitForResult();
3026 EXPECT_EQ(OK, rv);
3027}
3028
3029TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593030 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403031 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433032 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423033
3034 HttpRequestInfo request;
3035 request.method = "POST";
3036 request.url = GURL("http://www.google.com/");
3037
3038 MockWrite data_writes[] = {
3039 MockWrite("POST / HTTP/1.1\r\n"
3040 "Host: www.google.com\r\n"
3041 "Connection: keep-alive\r\n"
3042 "Content-Length: 0\r\n\r\n"),
3043 };
3044
3045 // Lastly, the server responds with the actual content.
3046 MockRead data_reads[] = {
3047 MockRead("HTTP/1.0 200 OK\r\n"),
3048 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3049 MockRead("Content-Length: 100\r\n\r\n"),
3050 MockRead(false, OK),
3051 };
3052
[email protected]5ecc992a42009-11-11 01:41:593053 StaticSocketDataProvider data(data_reads, data_writes);
3054 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423055
3056 TestCompletionCallback callback;
3057
[email protected]684970b2009-08-14 04:54:463058 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423059 EXPECT_EQ(ERR_IO_PENDING, rv);
3060
3061 rv = callback.WaitForResult();
3062 EXPECT_EQ(OK, rv);
3063}
3064
3065TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593066 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403067 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433068 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423069
3070 HttpRequestInfo request;
3071 request.method = "PUT";
3072 request.url = GURL("http://www.google.com/");
3073
3074 MockWrite data_writes[] = {
3075 MockWrite("PUT / HTTP/1.1\r\n"
3076 "Host: www.google.com\r\n"
3077 "Connection: keep-alive\r\n"
3078 "Content-Length: 0\r\n\r\n"),
3079 };
3080
3081 // Lastly, the server responds with the actual content.
3082 MockRead data_reads[] = {
3083 MockRead("HTTP/1.0 200 OK\r\n"),
3084 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3085 MockRead("Content-Length: 100\r\n\r\n"),
3086 MockRead(false, OK),
3087 };
3088
[email protected]5ecc992a42009-11-11 01:41:593089 StaticSocketDataProvider data(data_reads, data_writes);
3090 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423091
3092 TestCompletionCallback callback;
3093
[email protected]684970b2009-08-14 04:54:463094 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423095 EXPECT_EQ(ERR_IO_PENDING, rv);
3096
3097 rv = callback.WaitForResult();
3098 EXPECT_EQ(OK, rv);
3099}
3100
3101TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593102 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403103 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433104 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423105
3106 HttpRequestInfo request;
3107 request.method = "HEAD";
3108 request.url = GURL("http://www.google.com/");
3109
3110 MockWrite data_writes[] = {
3111 MockWrite("HEAD / HTTP/1.1\r\n"
3112 "Host: www.google.com\r\n"
3113 "Connection: keep-alive\r\n"
3114 "Content-Length: 0\r\n\r\n"),
3115 };
3116
3117 // Lastly, the server responds with the actual content.
3118 MockRead data_reads[] = {
3119 MockRead("HTTP/1.0 200 OK\r\n"),
3120 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3121 MockRead("Content-Length: 100\r\n\r\n"),
3122 MockRead(false, OK),
3123 };
3124
[email protected]5ecc992a42009-11-11 01:41:593125 StaticSocketDataProvider data(data_reads, data_writes);
3126 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423127
3128 TestCompletionCallback callback;
3129
[email protected]684970b2009-08-14 04:54:463130 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423131 EXPECT_EQ(ERR_IO_PENDING, rv);
3132
3133 rv = callback.WaitForResult();
3134 EXPECT_EQ(OK, rv);
3135}
3136
3137TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593138 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403139 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433140 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423141
3142 HttpRequestInfo request;
3143 request.method = "GET";
3144 request.url = GURL("http://www.google.com/");
3145 request.load_flags = LOAD_BYPASS_CACHE;
3146
3147 MockWrite data_writes[] = {
3148 MockWrite("GET / HTTP/1.1\r\n"
3149 "Host: www.google.com\r\n"
3150 "Connection: keep-alive\r\n"
3151 "Pragma: no-cache\r\n"
3152 "Cache-Control: no-cache\r\n\r\n"),
3153 };
3154
3155 // Lastly, the server responds with the actual content.
3156 MockRead data_reads[] = {
3157 MockRead("HTTP/1.0 200 OK\r\n"),
3158 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3159 MockRead("Content-Length: 100\r\n\r\n"),
3160 MockRead(false, OK),
3161 };
3162
[email protected]5ecc992a42009-11-11 01:41:593163 StaticSocketDataProvider data(data_reads, data_writes);
3164 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423165
3166 TestCompletionCallback callback;
3167
[email protected]684970b2009-08-14 04:54:463168 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423169 EXPECT_EQ(ERR_IO_PENDING, rv);
3170
3171 rv = callback.WaitForResult();
3172 EXPECT_EQ(OK, rv);
3173}
3174
3175TEST_F(HttpNetworkTransactionTest,
3176 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593177 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403178 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433179 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423180
3181 HttpRequestInfo request;
3182 request.method = "GET";
3183 request.url = GURL("http://www.google.com/");
3184 request.load_flags = LOAD_VALIDATE_CACHE;
3185
3186 MockWrite data_writes[] = {
3187 MockWrite("GET / HTTP/1.1\r\n"
3188 "Host: www.google.com\r\n"
3189 "Connection: keep-alive\r\n"
3190 "Cache-Control: max-age=0\r\n\r\n"),
3191 };
3192
3193 // Lastly, the server responds with the actual content.
3194 MockRead data_reads[] = {
3195 MockRead("HTTP/1.0 200 OK\r\n"),
3196 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3197 MockRead("Content-Length: 100\r\n\r\n"),
3198 MockRead(false, OK),
3199 };
3200
[email protected]5ecc992a42009-11-11 01:41:593201 StaticSocketDataProvider data(data_reads, data_writes);
3202 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423203
3204 TestCompletionCallback callback;
3205
[email protected]684970b2009-08-14 04:54:463206 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423207 EXPECT_EQ(ERR_IO_PENDING, rv);
3208
3209 rv = callback.WaitForResult();
3210 EXPECT_EQ(OK, rv);
3211}
3212
3213TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593214 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403215 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433216 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423217
3218 HttpRequestInfo request;
3219 request.method = "GET";
3220 request.url = GURL("http://www.google.com/");
3221 request.extra_headers = "FooHeader: Bar\r\n";
3222
3223 MockWrite data_writes[] = {
3224 MockWrite("GET / HTTP/1.1\r\n"
3225 "Host: www.google.com\r\n"
3226 "Connection: keep-alive\r\n"
3227 "FooHeader: Bar\r\n\r\n"),
3228 };
3229
3230 // Lastly, the server responds with the actual content.
3231 MockRead data_reads[] = {
3232 MockRead("HTTP/1.0 200 OK\r\n"),
3233 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3234 MockRead("Content-Length: 100\r\n\r\n"),
3235 MockRead(false, OK),
3236 };
3237
[email protected]5ecc992a42009-11-11 01:41:593238 StaticSocketDataProvider data(data_reads, data_writes);
3239 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423240
3241 TestCompletionCallback callback;
3242
[email protected]684970b2009-08-14 04:54:463243 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423244 EXPECT_EQ(ERR_IO_PENDING, rv);
3245
3246 rv = callback.WaitForResult();
3247 EXPECT_EQ(OK, rv);
3248}
3249
[email protected]3cd17242009-06-23 02:59:023250TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093251 SessionDependencies session_deps(
3252 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023253
3254 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433255 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023256
3257 HttpRequestInfo request;
3258 request.method = "GET";
3259 request.url = GURL("http://www.google.com/");
3260 request.load_flags = 0;
3261
3262 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3263 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3264
3265 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353266 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023267 MockWrite("GET / HTTP/1.1\r\n"
3268 "Host: www.google.com\r\n"
3269 "Connection: keep-alive\r\n\r\n")
3270 };
3271
3272 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593273 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023274 MockRead("HTTP/1.0 200 OK\r\n"),
3275 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3276 MockRead("Payload"),
3277 MockRead(false, OK)
3278 };
3279
[email protected]5ecc992a42009-11-11 01:41:593280 StaticSocketDataProvider data(data_reads, data_writes);
3281 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023282
3283 TestCompletionCallback callback;
3284
[email protected]684970b2009-08-14 04:54:463285 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023286 EXPECT_EQ(ERR_IO_PENDING, rv);
3287
3288 rv = callback.WaitForResult();
3289 EXPECT_EQ(OK, rv);
3290
3291 const HttpResponseInfo* response = trans->GetResponseInfo();
3292 EXPECT_FALSE(response == NULL);
3293
3294 std::string response_text;
3295 rv = ReadTransaction(trans.get(), &response_text);
3296 EXPECT_EQ(OK, rv);
3297 EXPECT_EQ("Payload", response_text);
3298}
3299
3300TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093301 SessionDependencies session_deps(
3302 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023303
3304 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433305 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023306
3307 HttpRequestInfo request;
3308 request.method = "GET";
3309 request.url = GURL("https://www.google.com/");
3310 request.load_flags = 0;
3311
3312 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3313 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3314
3315 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353316 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3317 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023318 MockWrite("GET / HTTP/1.1\r\n"
3319 "Host: www.google.com\r\n"
3320 "Connection: keep-alive\r\n\r\n")
3321 };
3322
3323 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353324 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3325 arraysize(read_buffer)),
3326 MockRead("HTTP/1.0 200 OK\r\n"),
3327 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3328 MockRead("Payload"),
3329 MockRead(false, OK)
3330 };
3331
[email protected]5ecc992a42009-11-11 01:41:593332 StaticSocketDataProvider data(data_reads, data_writes);
3333 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353334
[email protected]5ecc992a42009-11-11 01:41:593335 SSLSocketDataProvider ssl(true, OK);
3336 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353337
3338 TestCompletionCallback callback;
3339
[email protected]684970b2009-08-14 04:54:463340 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353341 EXPECT_EQ(ERR_IO_PENDING, rv);
3342
3343 rv = callback.WaitForResult();
3344 EXPECT_EQ(OK, rv);
3345
3346 const HttpResponseInfo* response = trans->GetResponseInfo();
3347 EXPECT_FALSE(response == NULL);
3348
3349 std::string response_text;
3350 rv = ReadTransaction(trans.get(), &response_text);
3351 EXPECT_EQ(OK, rv);
3352 EXPECT_EQ("Payload", response_text);
3353}
3354
3355TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093356 SessionDependencies session_deps(
3357 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353358
3359 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433360 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353361
3362 HttpRequestInfo request;
3363 request.method = "GET";
3364 request.url = GURL("http://www.google.com/");
3365 request.load_flags = 0;
3366
3367 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3368 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3369 const char kSOCKS5OkRequest[] =
3370 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3371 const char kSOCKS5OkResponse[] =
3372 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3373
3374 MockWrite data_writes[] = {
3375 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3376 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3377 MockWrite("GET / HTTP/1.1\r\n"
3378 "Host: www.google.com\r\n"
3379 "Connection: keep-alive\r\n\r\n")
3380 };
3381
3382 MockRead data_reads[] = {
3383 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3384 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3385 MockRead("HTTP/1.0 200 OK\r\n"),
3386 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3387 MockRead("Payload"),
3388 MockRead(false, OK)
3389 };
3390
[email protected]5ecc992a42009-11-11 01:41:593391 StaticSocketDataProvider data(data_reads, data_writes);
3392 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353393
3394 TestCompletionCallback callback;
3395
[email protected]684970b2009-08-14 04:54:463396 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353397 EXPECT_EQ(ERR_IO_PENDING, rv);
3398
3399 rv = callback.WaitForResult();
3400 EXPECT_EQ(OK, rv);
3401
3402 const HttpResponseInfo* response = trans->GetResponseInfo();
3403 EXPECT_FALSE(response == NULL);
3404
3405 std::string response_text;
3406 rv = ReadTransaction(trans.get(), &response_text);
3407 EXPECT_EQ(OK, rv);
3408 EXPECT_EQ("Payload", response_text);
3409}
3410
3411TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093412 SessionDependencies session_deps(
3413 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353414
3415 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433416 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353417
3418 HttpRequestInfo request;
3419 request.method = "GET";
3420 request.url = GURL("https://www.google.com/");
3421 request.load_flags = 0;
3422
3423 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3424 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3425 const unsigned char kSOCKS5OkRequest[] =
3426 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x01, 0xBB };
3427 const char kSOCKS5OkResponse[] =
3428 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3429
3430 MockWrite data_writes[] = {
3431 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3432 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3433 arraysize(kSOCKS5OkRequest)),
3434 MockWrite("GET / HTTP/1.1\r\n"
3435 "Host: www.google.com\r\n"
3436 "Connection: keep-alive\r\n\r\n")
3437 };
3438
3439 MockRead data_reads[] = {
3440 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3441 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023442 MockRead("HTTP/1.0 200 OK\r\n"),
3443 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3444 MockRead("Payload"),
3445 MockRead(false, OK)
3446 };
3447
[email protected]5ecc992a42009-11-11 01:41:593448 StaticSocketDataProvider data(data_reads, data_writes);
3449 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023450
[email protected]5ecc992a42009-11-11 01:41:593451 SSLSocketDataProvider ssl(true, OK);
3452 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023453
3454 TestCompletionCallback callback;
3455
[email protected]684970b2009-08-14 04:54:463456 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023457 EXPECT_EQ(ERR_IO_PENDING, rv);
3458
3459 rv = callback.WaitForResult();
3460 EXPECT_EQ(OK, rv);
3461
3462 const HttpResponseInfo* response = trans->GetResponseInfo();
3463 EXPECT_FALSE(response == NULL);
3464
3465 std::string response_text;
3466 rv = ReadTransaction(trans.get(), &response_text);
3467 EXPECT_EQ(OK, rv);
3468 EXPECT_EQ("Payload", response_text);
3469}
3470
[email protected]04e5be32009-06-26 20:00:313471// Tests that for connection endpoints the group names are correctly set.
3472TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3473 const struct {
3474 const std::string proxy_server;
3475 const std::string url;
3476 const std::string expected_group_name;
3477 } tests[] = {
3478 {
3479 "", // no proxy (direct)
3480 "http://www.google.com/direct",
3481 "http://www.google.com/",
3482 },
3483 {
3484 "http_proxy",
3485 "http://www.google.com/http_proxy_normal",
3486 "proxy/http_proxy:80/",
3487 },
3488 {
3489 "socks4://socks_proxy:1080",
3490 "http://www.google.com/socks4_direct",
3491 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3492 },
3493
3494 // SSL Tests
3495 {
3496 "",
3497 "https://www.google.com/direct_ssl",
3498 "https://www.google.com/",
3499 },
3500 {
3501 "http_proxy",
3502 "https://www.google.com/http_connect_ssl",
3503 "proxy/http_proxy:80/https://www.google.com/",
3504 },
3505 {
3506 "socks4://socks_proxy:1080",
3507 "https://www.google.com/socks4_ssl",
3508 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3509 },
3510 };
3511
3512 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093513 SessionDependencies session_deps(
3514 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313515
3516 scoped_refptr<CaptureGroupNameSocketPool> conn_pool(
3517 new CaptureGroupNameSocketPool());
3518
3519 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a937a06d2009-08-19 21:19:243520 session->tcp_socket_pool_ = conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313521
[email protected]5695b8c2009-09-30 21:36:433522 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313523
3524 HttpRequestInfo request;
3525 request.method = "GET";
3526 request.url = GURL(tests[i].url);
3527 request.load_flags = 0;
3528
3529 TestCompletionCallback callback;
3530
3531 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463532 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]04e5be32009-06-26 20:00:313533 EXPECT_EQ(tests[i].expected_group_name,
3534 conn_pool->last_group_name_received());
3535 }
3536}
3537
[email protected]9172a982009-06-06 00:30:253538TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543539 SessionDependencies session_deps(
3540 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323541
3542 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3543
[email protected]9172a982009-06-06 00:30:253544 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433545 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253546
3547 HttpRequestInfo request;
3548 request.method = "GET";
3549 request.url = GURL("http://www.google.com/");
3550
3551 TestCompletionCallback callback;
3552
[email protected]684970b2009-08-14 04:54:463553 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253554 EXPECT_EQ(ERR_IO_PENDING, rv);
3555
[email protected]9172a982009-06-06 00:30:253556 rv = callback.WaitForResult();
3557 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3558}
3559
[email protected]f3e6c1e2009-06-15 20:52:123560// Host resolution observer used by
3561// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3562// resovle requests are issued with a referrer of |expected_referrer|.
3563class ResolutionReferrerObserver : public HostResolver::Observer {
3564 public:
3565 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3566 : expected_referrer_(expected_referrer),
3567 called_start_with_referrer_(false),
3568 called_finish_with_referrer_(false) {
3569 }
3570
3571 virtual void OnStartResolution(int id,
3572 const HostResolver::RequestInfo& info) {
3573 if (info.referrer() == expected_referrer_)
3574 called_start_with_referrer_ = true;
3575 }
3576
3577 virtual void OnFinishResolutionWithStatus(
3578 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3579 if (info.referrer() == expected_referrer_)
3580 called_finish_with_referrer_ = true;
3581 }
3582
[email protected]eb255d32009-06-17 02:11:033583 virtual void OnCancelResolution(int id,
3584 const HostResolver::RequestInfo& info ) {
3585 FAIL() << "Should not be cancelling any requests!";
3586 }
3587
[email protected]f3e6c1e2009-06-15 20:52:123588 bool did_complete_with_expected_referrer() const {
3589 return called_start_with_referrer_ && called_finish_with_referrer_;
3590 }
3591
3592 private:
3593 GURL expected_referrer_;
3594 bool called_start_with_referrer_;
3595 bool called_finish_with_referrer_;
3596
3597 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3598};
3599
3600// Make sure that when HostResolver::Resolve() is invoked, it passes through
3601// the "referrer". This is depended on by the DNS prefetch observer.
3602TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3603 GURL referrer = GURL("http://expected-referrer/");
3604 EXPECT_TRUE(referrer.is_valid());
3605 ResolutionReferrerObserver resolution_observer(referrer);
3606
3607 SessionDependencies session_deps;
3608 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433609 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123610
3611 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143612 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123613
3614 // Connect up a mock socket which will fail when reading.
3615 MockRead data_reads[] = {
3616 MockRead(false, ERR_FAILED),
3617 };
[email protected]5ecc992a42009-11-11 01:41:593618 StaticSocketDataProvider data(data_reads, NULL);
3619 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:123620
3621 // Issue a request, containing an HTTP referrer.
3622 HttpRequestInfo request;
3623 request.method = "GET";
3624 request.referrer = referrer;
3625 request.url = GURL("http://www.google.com/");
3626
3627 // Run the request until it fails reading from the socket.
3628 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463629 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123630 EXPECT_EQ(ERR_IO_PENDING, rv);
3631 rv = callback.WaitForResult();
3632 EXPECT_EQ(ERR_FAILED, rv);
3633
3634 // Check that the host resolution observer saw |referrer|.
3635 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3636}
3637
[email protected]3b9cca42009-06-16 01:08:283638// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3639// host cache is bypassed.
3640TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3641 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323642
[email protected]a2c2fb92009-07-18 07:31:043643 // Select a host resolver that does caching.
3644 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323645
[email protected]3b9cca42009-06-16 01:08:283646 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433647 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:283648
3649 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3650 // a synchronous lookup.)
3651 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143652 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463653 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3654 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283655 EXPECT_EQ(OK, rv);
3656
3657 // Verify that it was added to host cache, by doing a subsequent async lookup
3658 // and confirming it completes synchronously.
3659 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463660 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283661 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463662 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323663 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283664
3665 // Inject a failure the next time that "www.google.com" is resolved. This way
3666 // we can tell if the next lookup hit the cache, or the "network".
3667 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323668 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283669
3670 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3671 // first read -- this won't be reached as the host resolution will fail first.
3672 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]5ecc992a42009-11-11 01:41:593673 StaticSocketDataProvider data(data_reads, NULL);
3674 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:283675
3676 // Issue a request, asking to bypass the cache(s).
3677 HttpRequestInfo request;
3678 request.method = "GET";
3679 request.load_flags = LOAD_BYPASS_CACHE;
3680 request.url = GURL("http://www.google.com/");
3681
3682 // Run the request.
3683 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463684 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283685 ASSERT_EQ(ERR_IO_PENDING, rv);
3686 rv = callback.WaitForResult();
3687
3688 // If we bypassed the cache, we would have gotten a failure while resolving
3689 // "www.google.com".
3690 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3691}
3692
[email protected]0877e3d2009-10-17 22:29:573693// Make sure we can handle an error when writing the request.
3694TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3695 SessionDependencies session_deps;
3696 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3697
3698 HttpRequestInfo request;
3699 request.method = "GET";
3700 request.url = GURL("http://www.foo.com/");
3701 request.load_flags = 0;
3702
3703 MockWrite write_failure[] = {
3704 MockWrite(true, ERR_CONNECTION_RESET),
3705 };
[email protected]5ecc992a42009-11-11 01:41:593706 StaticSocketDataProvider data(NULL, write_failure);
3707 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573708
3709 TestCompletionCallback callback;
3710
3711 scoped_ptr<HttpTransaction> trans(
3712 new HttpNetworkTransaction(CreateSession(&session_deps)));
3713
3714 int rv = trans->Start(&request, &callback, NULL);
3715 EXPECT_EQ(ERR_IO_PENDING, rv);
3716
3717 rv = callback.WaitForResult();
3718 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3719}
3720
3721// Check that a connection closed after the start of the headers finishes ok.
3722TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3723 SessionDependencies session_deps;
3724 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3725
3726 HttpRequestInfo request;
3727 request.method = "GET";
3728 request.url = GURL("http://www.foo.com/");
3729 request.load_flags = 0;
3730
3731 MockRead data_reads[] = {
3732 MockRead("HTTP/1."),
3733 MockRead(false, OK),
3734 };
3735
[email protected]5ecc992a42009-11-11 01:41:593736 StaticSocketDataProvider data(data_reads, NULL);
3737 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573738
3739 TestCompletionCallback callback;
3740
3741 scoped_ptr<HttpTransaction> trans(
3742 new HttpNetworkTransaction(CreateSession(&session_deps)));
3743
3744 int rv = trans->Start(&request, &callback, NULL);
3745 EXPECT_EQ(ERR_IO_PENDING, rv);
3746
3747 rv = callback.WaitForResult();
3748 EXPECT_EQ(OK, rv);
3749
3750 const HttpResponseInfo* response = trans->GetResponseInfo();
3751 EXPECT_TRUE(response != NULL);
3752
3753 EXPECT_TRUE(response->headers != NULL);
3754 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
3755
3756 std::string response_data;
3757 rv = ReadTransaction(trans.get(), &response_data);
3758 EXPECT_EQ(OK, rv);
3759 EXPECT_EQ("", response_data);
3760}
3761
3762// Make sure that a dropped connection while draining the body for auth
3763// restart does the right thing.
3764TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
3765 SessionDependencies session_deps;
3766 scoped_ptr<HttpTransaction> trans(
3767 new HttpNetworkTransaction(CreateSession(&session_deps)));
3768
3769 HttpRequestInfo request;
3770 request.method = "GET";
3771 request.url = GURL("http://www.google.com/");
3772 request.load_flags = 0;
3773
3774 MockWrite data_writes1[] = {
3775 MockWrite("GET / HTTP/1.1\r\n"
3776 "Host: www.google.com\r\n"
3777 "Connection: keep-alive\r\n\r\n"),
3778 };
3779
3780 MockRead data_reads1[] = {
3781 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3782 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3783 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3784 MockRead("Content-Length: 14\r\n\r\n"),
3785 MockRead("Unauth"),
3786 MockRead(true, ERR_CONNECTION_RESET),
3787 };
3788
[email protected]5ecc992a42009-11-11 01:41:593789 StaticSocketDataProvider data1(data_reads1, data_writes1);
3790 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:573791
3792 // After calling trans->RestartWithAuth(), this is the request we should
3793 // be issuing -- the final header line contains the credentials.
3794 MockWrite data_writes2[] = {
3795 MockWrite("GET / HTTP/1.1\r\n"
3796 "Host: www.google.com\r\n"
3797 "Connection: keep-alive\r\n"
3798 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3799 };
3800
3801 // Lastly, the server responds with the actual content.
3802 MockRead data_reads2[] = {
3803 MockRead("HTTP/1.1 200 OK\r\n"),
3804 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3805 MockRead("Content-Length: 100\r\n\r\n"),
3806 MockRead(false, OK),
3807 };
3808
[email protected]5ecc992a42009-11-11 01:41:593809 StaticSocketDataProvider data2(data_reads2, data_writes2);
3810 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:573811
3812 TestCompletionCallback callback1;
3813
3814 int rv = trans->Start(&request, &callback1, NULL);
3815 EXPECT_EQ(ERR_IO_PENDING, rv);
3816
3817 rv = callback1.WaitForResult();
3818 EXPECT_EQ(OK, rv);
3819
3820 const HttpResponseInfo* response = trans->GetResponseInfo();
3821 EXPECT_FALSE(response == NULL);
3822
3823 // The password prompt info should have been set in response->auth_challenge.
3824 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3825
3826 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3827 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3828 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3829
3830 TestCompletionCallback callback2;
3831
3832 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
3833 EXPECT_EQ(ERR_IO_PENDING, rv);
3834
3835 rv = callback2.WaitForResult();
3836 EXPECT_EQ(OK, rv);
3837
3838 response = trans->GetResponseInfo();
3839 EXPECT_FALSE(response == NULL);
3840 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3841 EXPECT_EQ(100, response->headers->GetContentLength());
3842}
3843
3844// Test HTTPS connections going through a proxy that sends extra data.
3845TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
3846 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
3847
3848 HttpRequestInfo request;
3849 request.method = "GET";
3850 request.url = GURL("https://www.google.com/");
3851 request.load_flags = 0;
3852
3853 MockRead proxy_reads[] = {
3854 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
3855 MockRead(false, OK)
3856 };
3857
[email protected]5ecc992a42009-11-11 01:41:593858 StaticSocketDataProvider data(proxy_reads, NULL);
3859 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:573860
[email protected]5ecc992a42009-11-11 01:41:593861 session_deps.socket_factory.AddSocketDataProvider(&data);
3862 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:573863
3864 TestCompletionCallback callback;
3865
3866 session_deps.socket_factory.ResetNextMockIndexes();
3867
3868 scoped_ptr<HttpTransaction> trans(
3869 new HttpNetworkTransaction(CreateSession(&session_deps)));
3870
3871 int rv = trans->Start(&request, &callback, NULL);
3872 EXPECT_EQ(ERR_IO_PENDING, rv);
3873
3874 rv = callback.WaitForResult();
3875 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3876}
3877
[email protected]e22e1362009-11-23 21:31:123878TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
3879 MockRead data_reads[] = {
3880 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
3881 MockRead(false, OK),
3882 };
3883 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
3884 EXPECT_EQ(OK, out.rv);
3885 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
3886 EXPECT_EQ("", out.response_data);
3887}
3888
[email protected]89ceba9a2009-03-21 03:46:063889} // namespace net